docs(product): design contract-wide id→handle request cutover (RIG-2751) - #645
Open
rigel-mintaka wants to merge 1 commit into
Open
docs(product): design contract-wide id→handle request cutover (RIG-2751)#645rigel-mintaka wants to merge 1 commit into
rigel-mintaka wants to merge 1 commit into
Conversation
Design record for the contract-wide id→handle cutover of the compass request surface (RIG-2751), per Matt's Option-A ruling: every request-input account field takes a `@handle`; the server resolves it to an account id exactly as the existing `from_handle` field does; no agent or client UI ever resolves an id; an unresolved handle surfaces as an in-band NOT_FOUND. ## Scope Field inventory verified complete against the current tree (all 7 proto files grepped): the request-input account fields across `comms.proto` (CreateChannel members, UpdateChannelMembers add/remove/subscribe/unsubscribe, ReparentAgent agent+new-parent, SetChannelPolicy owner, GetRoster vantage, OpenAgentWorkspace, CreateAgent parent) and `agent_gateway.proto` (DespawnPeer), plus the three new `CommsCallRequest` arms held in draft on #628 (re-authored handle-first here). `agents_spawn_peer` already takes a handle — the precedent this mirrors. Explicit non-goal (a decided boundary, not a reflex flip): response/stored/event fields keep ids — handing a handle back on a response pushes resolution onto the client, the opposite of the ruling. The one exception is surfaced in OQ-5. ## Design-critic pass folded Red-teamed by `CritiqueHandleCutover`; the architecture (edge-not-store resolution, in-band NOT_FOUND, dual-vantage-by-emptiness, T1-first sequencing) survived. Seven oracle-safety and grounding improvements folded: a per-handler NOT_FOUND remap table (two handlers today leak an unknown-vs-foreign oracle via PermissionDenied); T4's ordering preserves the lifecycle constant-query-shape bar; GetRoster's invisible-vantage posture is now defined, not inherited; the agent ListMessages author-id fence named as the concrete non-goal exception; error names all unresolved handles; a bounded skew window stated; and two load-bearing grounding corrections (the store returns ErrInvalidArgument, not NOT_FOUND, for unknown members). ## Open questions (freeze-gate decisions for Matt) - **OQ-1** — field naming (taste). - **OQ-1b** — field numbering: a CONFIRM of DL-186's rename-in-place, not an open fork. - **OQ-2** — repeated-field NOT_FOUND: a CONFIRM of atomic-failure, error naming all unresolved handles. - **OQ-3** — GetRoster vantage field name (taste). - **OQ-4** — compass.proto admin lane: extend the ruling to the 3 admin fields or keep ids (real scope fork). - **OQ-5** — response handles: ship the DL-NEW-2 additive `author_handle` sibling with this cutover (the agent's ListMessages author-id fence is the identified surface) or defer. - **OQ-6 (NEW, load-bearing)** — member-resolution visibility scoping: (a) viewer-scoped `AccountsByHandles` [rec — the only option consistent with the oracle posture] vs (b) unscoped; T2's resolver signature depends on this ruling. ## Ledger-impact DL-NEW-1 (handle-typed request inputs, server-edge resolution, one indistinguishable in-band NOT_FOUND), DL-NEW-2 (responses/stored/events keep ids; display handles only as additive sibling fields). No existing DL row constrains request addressing (DL-094/186/188/191/202 checked; DL-186 rules the rename-in-place field-numbering). Next-free ids assigned at freeze. Ref: RIG-2751 Co-authored-by: Matt Wilkinson <matt@rigel.build>
|
Compass engineering docs preview: https://compass-server-rig-2751-hand.compass-eng-docs.pages.dev Deployed from Changed pages: |
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.
Design record for the contract-wide id→handle cutover of the compass request surface (RIG-2751), per Matt's Option-A ruling: every request-input account field takes a
@handle; the server resolves it to an account id exactly as the existingfrom_handlefield does; no agent or client UI ever resolves an id; an unresolved handle surfaces as an in-band NOT_FOUND.Scope
Field inventory verified complete against the current tree (all 7 proto files grepped): the request-input account fields across
comms.proto(CreateChannel members, UpdateChannelMembers add/remove/subscribe/unsubscribe, ReparentAgent agent+new-parent, SetChannelPolicy owner, GetRoster vantage, OpenAgentWorkspace, CreateAgent parent) andagent_gateway.proto(DespawnPeer), plus the three newCommsCallRequestarms held in draft on #628 (re-authored handle-first here).agents_spawn_peeralready takes a handle — the precedent this mirrors.Explicit non-goal (a decided boundary, not a reflex flip): response/stored/event fields keep ids — handing a handle back on a response pushes resolution onto the client, the opposite of the ruling. The one exception is surfaced in OQ-5.
Design-critic pass folded
Red-teamed by
CritiqueHandleCutover; the architecture (edge-not-store resolution, in-band NOT_FOUND, dual-vantage-by-emptiness, T1-first sequencing) survived. Seven oracle-safety and grounding improvements folded: a per-handler NOT_FOUND remap table (two handlers today leak an unknown-vs-foreign oracle via PermissionDenied); T4's ordering preserves the lifecycle constant-query-shape bar; GetRoster's invisible-vantage posture is now defined, not inherited; the agent ListMessages author-id fence named as the concrete non-goal exception; error names all unresolved handles; a bounded skew window stated; and two load-bearing grounding corrections (the store returns ErrInvalidArgument, not NOT_FOUND, for unknown members).Open questions (freeze-gate decisions for Matt)
author_handlesibling with this cutover (the agent's ListMessages author-id fence is the identified surface) or defer.AccountsByHandles[rec — the only option consistent with the oracle posture] vs (b) unscoped; T2's resolver signature depends on this ruling.Ledger-impact
DL-NEW-1 (handle-typed request inputs, server-edge resolution, one indistinguishable in-band NOT_FOUND), DL-NEW-2 (responses/stored/events keep ids; display handles only as additive sibling fields). No existing DL row constrains request addressing (DL-094/186/188/191/202 checked; DL-186 rules the rename-in-place field-numbering). Next-free ids assigned at freeze.
Ref: RIG-2751
Co-authored-by: Matt Wilkinson matt@rigel.build