Tower passports on the job API¶
How does an agent holding a Tower passport call hangar's job API as the person it works for? This page is for the admin who turns that on. The contract is spec 0015.
Turning it on¶
HANGAR_JOB_PASSPORTS=on makes /api/jobs and every route under it accept a passport as the bearer. It is off by default, and hangar's own tokens work as before either way.
| Setting | Default | What it is |
|---|---|---|
HANGAR_JOB_PASSPORT_ISSUER |
HANGAR_GOVERNANCE_URL |
Tower's URL: the passport's issuer, and where its keys are published |
HANGAR_JOB_PASSPORT_AUDIENCE |
<issuer>/mcp and <issuer> |
The audiences accepted, comma-separated |
HANGAR_JOB_PASSPORT_AGENTS |
empty | Agents that may act as themselves, as agent=person,... |
With no issuer set, hangar accepts no passport and says so in its log.
Tower mints passports only for its own audiences, so hangar accepts those by default. A passport an agent holds for Tower's gateway therefore also works here. It acts only as the person it names, and only once an admin turns this on.
What hangar checks¶
hangar reads Tower's keys from <issuer>/.well-known/jwks.json and checks each passport before it acts:
- an EdDSA signature by a key Tower publishes;
- the issuer and the audience;
- the expiry, with 60 seconds of clock skew;
- the chain of agents and its
actclaim, at most three agents.
A tampered, expired, wrong-audience or unknown-issuer passport is refused with 401. So is one whose subject hangar can't name. Every refusal is audited passport.refused, without the token.
Who the caller is¶
| Subject | Runs as |
|---|---|
person:<email> |
The hangar person that email is linked to: hangar person link alice email alice@example.com |
agent:<id> |
The person listed for that agent in HANGAR_JOB_PASSPORT_AGENTS |
| Anything else | Refused |
The caller holds the jobs scope only, as a service token does. It sees only the jobs it submitted, under that person's caps. A passport never approves or rejects a job: it always names an agent, and approving is a person's own act.
How Tower sees hangar's people¶
When hangar asks Tower about a release or a landing, it names each person in the form Tower uses:
- the hangar person, and the email linked to them;
- a GitHub account as
github:<login>, with the login GitHub reported in the same event; - a Jira account as
jira:<account id>.
Tower maps a person by the email first. github:<login> maps only when Tower's hangar.people map has that key, so link each person's email in hangar.
hangar finds the person from the account's numeric id, never from the login, because a renamed login can be registered by someone else. When only the id is known, hangar sends github-id:<id>, which Tower maps to nobody. An unmapped signer leaves the approval waiting.