feat(core): track authorization state at consensus - #448
Open
rickyrombo wants to merge 1 commit into
Open
Conversation
rickyrombo
force-pushed
the
feat/consensus-auth-state
branch
from
August 6, 2026 08:01
7fa5175 to
ad7d6e8
Compare
rickyrombo
force-pushed
the
feat/consensus-auth-state
branch
from
August 6, 2026 08:26
ad7d6e8 to
0dec4c1
Compare
Adds the core_auth_* tables — users, grants, developer apps, entity ownership — as a consensus-maintained projection of the authorization-relevant subset of ManageEntity effects. FinalizeBlock applies the projection inside the block's transaction for both live and genesis-migration transactions, so every validator holds an identical answer to 'is this signer allowed to act for this user?' without consulting the (non-consensus) ETL. The projection mirrors the ETL's entity_manager handlers — validate, then apply — so consensus state tracks what the ETL actually indexes: wallet/handle uniqueness on live user creates (relaxed for migration replay, where legacy source data is the authority), signer authority via own-wallet or active approved grants, grantee liveness, entity ownership on create/delete, and the grant create/approve/reject/revoke lifecycle. Content semantics (titles, genres, gating) stay in the ETL on purpose. Nothing reads this state yet: enforcement arrives separately behind an upgrade-schedule height gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
rickyrombo
force-pushed
the
feat/consensus-auth-state
branch
from
August 6, 2026 08:36
0dec4c1 to
bccecad
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Stacked on #447. Adds consensus-maintained authorization state: the
core_auth_*tables (users, grants, developer apps, entity ownership), populated byFinalizeBlockinside the block's pg transaction for both liveManageEntityand genesis-migration transactions. Every validator ends up with an identical, deterministic answer to "is this signer allowed to act for this user?" — without consulting the (non-consensus) ETL.Nothing reads this state yet. Enforcement lands separately behind an upgrade-schedule height gate (next PR in the stack).
Design
Validate-then-apply, mirroring the ETL. The projection (
pkg/core/server/auth_state.go) restates the auth-relevant rules of the ETL'sentity_managerhandlers:ValidateSigner(own wallet, or an active non-revoked grant whose grantee is a live app or active user, approved for user-to-user manager grants), wallet/handle/app-address/entity-id uniqueness, ownership on delete, and the grant create → approve/reject → revoke lifecycle. A tx whose auth effects the ETL would reject is skipped here too — otherwise the projection would accumulate state from rejected txs and, once enforcement exists, that state would be authoritative. This matters most in the pre-enforcement window.Migration replay is relaxed exactly where the ETL relaxes it. Migration txs keep signer-authority checks (genesis-writer signs as the owning user) but drop wallet/handle uniqueness and ID offsets — legacy source data is the authority on those, and can contain collisions. Deleted tracks/playlists replay with their deleted flag. This means the genesis replay leaves behind a complete auth state, which is what the first live transaction after the migration boundary will validate against.
Deliberately not mirrored: content rules (title required, genre validity, gating conditions). Consequence documented in the file: a tx the ETL rejects on a content rule still projects here if its authorization is valid, so that entity id reads as taken. That conservative approximation is the price of keeping content semantics out of consensus.
Determinism: reads by primary key only, addresses/handles lowercased at write time, no clocks,
ErrNoRows= absent (never an error), all writes conflict-safe so replay is idempotent. Store failures are logged without failing the tx, matching how the rest ofFinalizeBlocktreats local db errors.Current-state only: unlike the ETL's history-keeping tables (
is_currentrows),core_auth_grantsholds one row per (grantee, grantor) pair — consensus only ever asks about the present.Testing
auth_state_test.goruns the projection against a map-backed store: wallet/handle uniqueness (live vs migration), app-grant auto-approval and revocation, the user-to-user pending → approve/reject lifecycle, grantee-side revocation, ownership-checked deletes, deactivation ending grantee liveness, and the{\"cid\":...,\"data\":{...}}metadata envelope unwrap.go test ./pkg/core/server/green.🤖 Generated with Claude Code