feat(identity): bind account capability to current link event - #222
seonghobae wants to merge 24 commits into
Conversation
A buyer who links an anonymous assessment to a Keyverse account must still see that link after process restart. Persist assessment_participant plus append-only link and link-end evidence, reload through the domain lifecycle, and fail closed on conflicting replay or a subject already bound to another participant. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Keep TRACEABILITY, ADR-0020, ERD, and as-built schema pointing at the opened persist/reload vehicle instead of an unnamed Active PR. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Apply each identity link and then its matching ends in one transaction so a complete in-memory unlink+relink aggregate survives restart. Cover one-shot persist, exact replay, and subject reuse after unlink. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Add a tenant-scoped current-subject lookup so a returning Keyverse login can find the same product-owned participant after the anonymous session token is gone. Ended or replaced subjects stay unfindable until they are current again. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Remove the accidentally committed build tree and ignore /target so later local verification cannot leak compiler outputs into the identity-link successor. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
A missing current_participant_identity_link row no longer hides a returning Keyverse login or lets another participant bind the same issuer-scoped subject. Lookup and uniqueness now read append-only link rows that have no matching end. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Name the Active PR vehicle as the successor of #124 so TRACEABILITY, ADR-0020, and the as-built schema do not treat projection-only lookup as the landing contract. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Exact replay of the same identity-link history now reconciles the derived current projection so operator repair cannot hide a returning login behind a missing unique enforcer or leave a stale row after unlink. Name Active PR #133 in TRACEABILITY instead of superseded #124. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
A buyer who proves control of both the anonymous session and a Keyverse account can persist that link and later recover the same product-owned participant from a still-valid account proof. Expired proofs fail before persist or lookup. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Point TRACEABILITY, ADR-0020, UML, and the as-built schema at the hosted dual-proof persist/recover commands so operators do not treat persist-only #147 as the last identity-link landing vehicle. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
A still-valid account proof must not receive a participant whose current tenant, issuer, or subject no longer match that proof. Keep the loaded record only when the current binding still matches, and cover expired, other-tenant, and ended-subject recover paths. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Keep TRACEABILITY, ADR-0020, ERD, and the as-built schema pointing at the opened recover current-binding successor instead of an unnamed #160 follow-up. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Add hosted unlink so a still-valid Keyverse proof can end the matching current binding. Reload stored history before authorization so a stale in-memory record cannot unlink a rebound subject. Exact replay is idempotent; expired proofs and unused accounts fail closed. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Unlink already stops recover from returning the participant. A previously recovered participant_ref could still be treated as an account grant. Bind that grant to the current link_event_ref and re-check it so unlink or rebound fails closed. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A grant issued against a stored current binding must fail closed after persist_authorized_account_unlink, matching recover returning None. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Assessment
Unique slice on c3531c7 is SOUND for the grant/accept gate. grant_account_linked_capability binds the grant to the current link_event_ref. accept_account_linked_capability re-checks proof expiry, unknown time, foreign-tenant proof, and current participant/tenant/issuer/subject/link_event_ref. Unlink or rebound fails closed. Anonymous assessment sessions stay on participant_ref. No public constructor can forge AccountLinkedCapability.
Queue
Prefer #236 a667395 for the unique event-bind proof: same-subject relink under a new link_event_ref must reject the ended grant, including accept against load_participant_identity_history. Prefer #222 for the grant/accept introduction if #236 is not the landing vehicle. Prefer #206 for persist unlink. Keep #202/#210 inspect-line. Keep #158 restore.
Do not merge #215 over this head. That HTTP recover path does not call accept_account_linked_capability and still races persist files.
Next after check-clean
HTTP account-link transport (OpenAPI 3.2.x, RFC 9457) must reload current history in the same transaction as the privileged command, then call accept_account_linked_capability. Do not fold live Keyverse verification into that slice. Do not invalidate anonymous sessions on unlink.
Do not merge until exact-head checks and independent last-push approval are satisfied. Never self-approve.
Sent by Cursor Automation: Fix Issues
|
Closing as superseded, not merged. Fresh ancestry proof shows #236 head |


Why
PR #206 ends a matching current Keyverse binding and makes later recover return
None. A buyer who already recovered that participant still held aparticipant_refthat could be treated as an account grant after unlink or rebound. Assessment sessions stay on the stable participant; only account-linked capability must die with the currentlink_event_ref.TDD
RED
grant_account_linked_capabilityandaccept_account_linked_capabilitywere missing. GREEN grants a capability bound to the current link event, accepts it only while that binding still matches, rejects the grant after unlink or rebound, and fails closed on expired, unknown-time, or foreign-tenant proofs.Scope
Out of scope
participant_ref)Operator next action
Review the link-event-bound account capability. Prefer #206 for persist unlink. Do not merge #206, #176, #160, #147, #133, #124, or #114 as substitutes for this grant/accept gate. Do not merge this PR until exact-head checks and independent last-push approval are satisfied. Never self-approve.