Z5: per-subject credential resolution in static-inject (RFC 8693)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 13
- Forks
- 40
- Avg merge
- 12h 17m
- Merged PRs (30d)
- 156
Description
What this is
Give a tracked home to the deferred per-user half of Z5. This is not a new design: docs/specs/2026-06-19-m13-generalized-credentialed-egress-design.md already specifies generalized credentialed egress, and docs/specs/README.md:152 records that RC1 implements "a static single-tenant slice of Z5 (per-user / RFC 8693 deferred)". This issue is that deferred half.
Please read Z5 and ADR-0006 as the design; this issue records the seam and the open tension rather than restating them.
Why now
rossoctl/serverless-harness is splitting its multi-session work (issue #220 there) into three slices. Two are harness-local; the third is this one. The harness slice — rossoctl/serverless-harness#239 — makes the harness send a per-request subject and carry an inert placeholder instead of a real key. Nothing consumes that subject until static-inject can resolve a credential from it.
Until then the harness slice makes the system tenancy-neutral, not multi-tenant safe. That boundary should not be advertised as closed until this lands.
Goal
ADR-0006's (subject ⊕ destination) → credential resolution. Today static-inject resolves by destination host or a static key (ADR-0026) — one credential per deployment.
The seam
authbridge/authlib/plugins/staticinject/resolver.go:20-28 defines:
Resolve(ctx, key string) (string, bool)
implemented only by MapResolver (:28-31) and a secret_dir-style FileResolver (:39-49). Per-subject resolution makes that key subject-derived rather than destination-derived.
Prior art in this repo
authbridge/authlib/plugins/tokenbroker/plugin.go:281-294 already extracts a subject token from the inbound Authorization: Bearer header and exchanges it via client.AcquireToken. The exchange machinery exists; what is missing is static-inject keying on the result.
Design tension to settle first
The two plugins disagree about which header carries the subject:
- P5 deliberately keeps inbound
Authorizationfree for caller authentication, and carries the placeholder on egressAuthorization: Bearer <placeholder>(the harness sets'x-api-key': nullatrun-turn.ts:337), with the subject on a separateX-SH-Subject. tokenbrokerexpects the subject token on the hop'sAuthorization.
Worth resolving before implementation, since it decides whether static-inject reads the subject from a dedicated header or from an exchanged token.
Note on repo naming
The harness specs and ADR-0032 still refer to this repo as kagenti-extensions, which now redirects here. Worth correcting on both sides as those docs are touched.
Blocked by
rossoctl/serverless-harness#239 — the injector cannot key on a subject the harness does not yet send.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read docs/specs/2026-06-19-m13-generalized-credentialed-egress-design.md, docs/specs/README.md, and ADR-0006 first. Inspect authbridge/authlib/plugins/staticinject/resolver.go:20-49 and tokenbroker/plugin.go:281-294, then resolve the Authorization versus X-SH-Subject contract, noting the dependency on serverless-harness#239. Done means the deferred per-subject resolution seam is implemented and the tenancy boundary is no longer merely neutral.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- authentication, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100