All notable changes to this project are documented here. The format follows Keep a Changelog, and this project adheres to Semantic Versioning.
[0.1.0] — 2026-08-08
First release.
Not yet verified against production
AshOpenFeed.revoke/2 and the success path of AshOpenFeed.refresh_status/2
require the openfeed-au:grant:self:query and openfeed-au:grant:self:revoke
scopes, which the registration used for development was not granted. Both are
covered by tests against a stub server, but neither has been exercised against
the real API. Everything else here has.
reconcile_grants/2 has been run against production, including its
degradation path when those scopes are absent.
Requires
- Elixir 1.17+ and OTP 27+. The OTP floor comes from oidcc, which does not compile on OTP 26; both packages check and raise a clear error. Verified in CI across Elixir 1.17-1.20.
Added
AshOpenFeed.Grant— Ash resource extension. Injects the token attributes, thegrant_ididentity and the lifecycle actions into a resource you own. Uses Ash'sadd_new_*builders throughout, so your own declarations win.AshOpenFeed— runtime API:authorize_url/3,complete_authorization/4,access_token/2,with_token/3,revoke/2,refresh_status/2.AshOpenFeed.Info— introspection, plusconfig/2resolving anOpenFeed.Configfrom application config or a provider.AshOpenFeed.ConfigProvider— behaviour for credentials that cannot come from static config, such as a registration per tenant.AshOpenFeed.KeyStore.Ash— signing key in an Ash resource, so every node signs with the same key.mix ash_openfeed.install— Igniter installer. Generates the domain, grant and key resources, an editable consent controller, routes and config.- Compile-time verifiers: one rejecting a resource with no credential source, one warning when tokens have no visible encryption at rest.
Added
AshOpenFeed.amend_url/3— send a consumer back to OpenFeed to change which accounts they share. OpenFeed keeps the samegrant_idand bumps its revision, so the existing callback handles the return trip.AshOpenFeed.reconcile_grants/2— diff local grants against OpenFeed's app-level index. There are no webhooks, so this is the only way to notice a revocation or amendment without first failing a data call. Phase one needs only the app-level scope, so it works without grant-management scopes; phase two degrades gracefully, still recording the revision.banking_account_ids/energy_account_idsattributes and async_grant_stateaction.
Fixed
- A rejected refresh now marks the grant revoked. Previously
with_token/3'swithshort-circuited onaccess_token/2, so a refresh failure never reached reconciliation and the grant stayed:activeindefinitely. refresh_status/2read onlygrantStatusandmeteringState, discarding the rest of the response. It now mapsgrantRevisionand the authorised account id sets too — the injectedrevisionattribute was previously never written.complete_authorization/4warns whengrant_management? truebut the scopes were not granted, rather than lettingrevoke/2fail with a 403 at the moment a consumer is trying to disconnect.
Documentation
- A Collecting data into your own resources section: the full sync loop, error collection, streaming large collections, and an AshOban schedule. Previously a single line.
Notes
- The injected identity gets
pre_check_withautomatically on data layers that cannot enforce identities (ETS, Mnesia), since the identity is injected and could not otherwise be fixed by the user. Because a pre-checked identity installs abefore_actionhook,require_atomic? falseis applied to the update actions in exactly that case — AshPostgres keeps atomic updates.