Design: flow login, profiles, and the attestable identity chain from GHA to Temporal
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 9
- Forks
- 0
- Avg merge
- 3h 3m
- Merged PRs (30d)
- 509
Description
Two related gaps, one for humans and one for the audit trail — the workload half of the chain already works and is worth stating first so the design builds on it rather than reinventing it.
What is already true
A GitHub Actions job can start a Flowstate workflow today with no stored secret anywhere: the trust policy names GHA's issuer with claim rules (repository, ref, environment — exact-match any_of, deliberately no wildcards), the job presents its OIDC token via FLOWSTATE_TOKEN="$(gha-oidc-token)", the server verifies against GitHub's JWKS, derives the tenant from a claim, records the identity in RunState.Identity and the namespace memo, sets the fairness key, and — since #103 — routes to the mapped Temporal namespace and carries the named claims into the run's WorkloadIdentity. That is GHA → Flowstate → Temporal with the identity attached at every hop. The pieces are coherent; what is missing is the human path and the legibility of the chain.
flow login, and profiles
Today a human authenticates by exporting FLOWSTATE_TOKEN from wherever they can get one (gcloud auth print-identity-token is the documented example), and --token deliberately does not exist (a credential in argv is a credential in ps — keep that refusal). What is missing:
flow login— OAuth device flow against the deployment's configured IdP: the server's discovery document (already published at/.well-known/...when federating) grows the fields a client needs,flow loginopens the browser or prints the device code, and the resulting token is cached with 0600 discipline and refreshed while refreshable. Fail-visible:flow login statussays who you are, to which deployment, expiring when — the answer to "why am I getting 401" that today requires decoding a JWT by hand.- Profiles, following the precedent already in the repo: the Temporal connection already honours
TEMPORAL_PROFILEand the temporal CLI's own TOML — adopting the ecosystem's convention rather than inventing one is recorded as a deliberate choice in ARCHITECTURE.md. Flowstate's client config should take the same shape: aFLOWSTATE_PROFILEselecting{address, auth method, token cache, default namespace}from one file, soflow --profile staging run …and CI's env-var-only path are the same code resolving the same precedence (flags > env > profile > default). One resolution order, documented once, tested once. - Profiles do not hold tokens — they name where tokens come from (an IdP for the device flow, a file for CI, an env var). The cache is per-profile state beside, not inside, the profile.
The attestable chain, end to end
The enterprise question is "who caused this step to call that API, prove it" — and every hop already has the data; the work is making it one legible chain:
- Inbound attestation: record in the run (not just derive from) the verified issuer, subject, and the claims that were checked — the trust-policy decision, content-addressed like #104 proposes for policies, so "which rules admitted this caller" is answerable after the rules change.
- Through Temporal: the identity already rides
RunStateand the memo; Temporal's own RBAC applies below the namespace mapping (#107). A reader of Temporal history sees the same identity Flowstate enforced — no parallel truth. - Outbound attestation: #94's assertions already carry
on_behalf_of/on_behalf_of_issuerplus the per-step subject (flowstate:<ns>/<deployment>/<workflow>/<step>) — so the STS session at AWS names the workload and the CI job that asked for it, with the hashed session-name discipline from #75 preventing tenant spoofing. When #94 wires the broker into activities, the chain closes: GHA job → Flowstate run → step → cloud credential, every link signed, short-lived, and audience-scoped, no standing secret at any hop. flow trace-shaped legibility (the fourth-round CLI doctrine already names it): one command answering the whole chain for a run — who started it, under which trust rules, which identities each step assumed, against which policies — from data the run already carries rather than a SIEM expedition.
Constraints
Invariant 8: all of it optional — --insecure-no-auth local development keeps working with zero configuration, and flow login against a deployment with no IdP configured says so plainly. The device-flow secret handling follows the secrets discipline (cached token never logged, never in argv, 0600, containment-shape tested). Admin surface for managing trusted issuers at runtime is #107's; this issue is the client half and the chain's legibility.
Related: #107 (control plane — issuer management), #94 (outbound federation — the chain's far end), #104 (policy digests — the "under which rules" attestation), #93/#103 (the inbound wiring this builds on).
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
Start with ARCHITECTURE.md and the existing TEMPORAL_PROFILE and Temporal CLI configuration precedent. Map the entry points for flow login, flow login status, profile resolution, and flow trace, then review the related work in #93, #103, #104, #107, and #94. Done means an agreed design covering human login, profile precedence, and a legible attested chain without weakening the stated constraints.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, github-actions, go
- Domain
- authentication, cli, cloud, distributed-systems, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100