Repository navigation
Establish asking-viewer authority for an installed module first source call #1200
Description
A consuming module needs one read-only source call whose owner is the asking viewer and whose actor is the independently authenticated installed module. The current public paths provide either the viewer without a module actor or unattended authority owned by the person who connected the source. Neither establishes that combination. This is a source/design finding, not a recovered historical consumer failure.
Part of #1023. Inspected host baseline/tag 2cb00737ed56c79c823bc82f4055681a51919e7c / v0.0.103; scoped-read candidate #1197 is independent and does not supply first admission.
Public path trace
WorkContextService/StartTaskwith no actor derives the asking owner and issues a direct viewer context. Its actor arm andStartChildSessionresolve a registered agent throughpostgres_work_context_authority.go, requiring an active organization-scopedprincipals.kind = agentrow and that agent’s RBAC. The declared module is instead a derived service principal, not a directory row. Creating a second agent identity with the module’s label would not prove the delivered module’s identity.- Module operation exchange authenticates the module and viewer parent independently, checks installed binding/tenant/current authority, and calls
exchangeVerifiedParent. The empty parent chain remains empty. fix(accounts)!: a module's operation child is derived from the presented parent and carries its session #1124 expressly preserves that chain while correcting lineage; it is not a first-actor operation. MintSourceOperationContextand the delegation-reference arm append a module service actor, but owner comes from the connected source’s stored delegation. They serve unattended borrowed authority and must retain that meaning.- Module identity/headless mints own work as the module; registered-client token exchange, escalation grants, gateway forwarding and context renewal do not establish the required first module actor for a viewer either.
The counterexample is shared source S connected by administrator A and queried by viewer B. B’s call must remain owned by B, even if A has an unattended delegation. B’s missing source permission must not be replaced with A’s authority. A personal source makes the same distinction consequential for disclosure.
Callee and audit must agree with admission
Simply issuing a Core Child is insufficient. authenticateSourceOperationContext recognizes source-delegation parents specially; ordinary actor chains flow to requireCurrentAuthority, which currently uses the registered-agent authority store. Reuse the existing installed-module binding confirmation, seal/epoch and current viewer source access so a valid admitted child can be revalidated at the source callee without inventing a directory row.
Source-call audit also needs the two identities. Source ingress stamps the owner as ordinary request identity, while retaining the Work Context in a private adapter key. Invoke obtains callerID from that owner; AuditSourceOperation currently emits it as actor type user. Exchange/mint observations do not make the source operation event itself retain both owner and authenticated module actor. This is a pre-existing source trace finding, not a live stored-event observation; coordinate #1123’s separate scope-refusal coverage.
Relevant owner files at the inspected revision: pkg/adapters/work_context_rpcs.go, work_context_core.go, delegated_read_audience.go, source_delegation.go, source_operation_authority.go; pkg/infra/postgres_work_context_authority.go; pkg/business/module_hop_binding.go and source_operation_invoke.go under the Accounts code root.
Owner decision before implementation
The identity outcome and host ownership are already established by the handbook’s composition/callable-source obligations. The public operation or explicit mode for establishing the first module hop still needs owner agreement. Proposed direction: extend the existing module authority surface using independent verified module identity, verified asking-viewer parent addressed to that module, current installation/consent and an admitted operation binding; derive owner/tenant/lineage from the parent and actor from the module proof; use Core Child and existing binding/authority/audit machinery. Preserve the chain-preserving exchange contract. No second registry, custody store, permission vocabulary, provider client or durable loop.
Do not silently broaden StartTask’s registered-agent contract or allow caller-asserted owner/actor identities. Coordinate SDK adoption with existing codefly-dev/saas-sdk-go#45/#47 after the owner contract is reviewed/published.
First bounded acceptance
Through generated transport and source ingress, verify:
- Asking viewer B is owner; independently authenticated installed module M is the final service actor. B’s actual source access remains decisive.
- Binding/source/invoke or lookup-only scopes are exact; wrong module, tenant, source, binding or broader requested authority refuses before provider dispatch.
- Membership/source access loss, personal-source mismatch, installation withdrawal and binding narrowing take effect after a prior successful call.
- Child lineage derives from the presented parent and expiry never exceeds it.
- The source operation audit retains both B and M without credentials, URLs, input or output.
- Connector A’s unattended grant cannot replace B’s parent or turn B’s refusal into success.
Qualification to date: fresh independent source/design review, no implementation or live composition claim. A focused test attempt could not compile because local disk filled; no actor-path test pass is claimed. Existing source storage, Work Context signing, binding confirmation and current reader checks should be reused. No merge, release or deployment is requested.
Activity
feat(accounts): a module_actor binding names the exchanging module as…
feat(accounts): module_actor names only what its audience serves, and…
feat(accounts): a module_actor binding names the exchanging module as…
test(accounts): pin the module_actor child's payload for every audien…