Metadata-Version: 2.5
Name: veltro-suite-auth
Version: 3.1.3
Summary: Veltro-owned suite authentication contracts.
Project-URL: Repository, https://github.com/veltrosecurity/veltro
Author: Veltro Security
License-Expression: AGPL-3.0-or-later
License-File: LICENSE
License-File: NOTICE
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: cryptography>=45.0.1
Requires-Dist: joserfc==1.7.5
Description-Content-Type: text/markdown

# veltro-suite-auth

Veltro-owned suite session and service-token contracts with signed-realm compatibility.

This package is derived from the AGPL-3.0-or-later `veltro-suite-auth` 1.3.0 implementation originally maintained in VectorFlow. See `NOTICE` for provenance.

## JOSE dependency (3.1.3)

3.1.3 uses `joserfc==1.7.5` and `cryptography>=45.0.1`. Auth.js cookies
keep `dir`/`A256CBC-HS512` encryption and cookie-specific HKDF keys.
Authority envelopes and browser request assertions keep ES256 signatures
and the existing claim, replay and request-binding checks.

The compact session limit remains 256,000 bytes. Existing large payloads,
chunked cookies and legacy DEF-compressed sessions remain supported.

Update the installed `veltro-suite-auth` pin to take this change. Older SDK
versions still install `python-jose` transitively, even when the product removes
its direct dependency.

## Removed in 3.0.0

3.0.0 drops the authority-revision module: `verify_authority_revision_v1`, the
watermark apply, restore and availability helpers, their constants and types,
and the `REV_*` error codes. Identity never minted revisions, and revocation
already applies on the next request because identity re-reads grants for every
assertion, token call and exchange (veltro#129). A product that imported any of
these has to delete that receiver before it takes 3.0.0.

## Native roles

`APP_ROLES` lists the roles each product accepts. From 2.5.0, VectorFlow and
CHAD also accept `approver`, which maps to the coarse `editor` suite role on
service tokens and authority envelopes, as Warden's already did. An older
decoder rejects the whole session or token when it sees a role it doesn't
know, so a product has to ship 2.5.0 or later before an admin grants anyone
the VectorFlow or CHAD approver role.

## Authority envelope v2

From 2.6.0, the actorless `settings:read` and `settings:write` scopes are valid
for the `vectorflow` audience too, not just `chad` and `warden`. Identity
uses them to write each product's AI settings (veltro#1150).

From 3.1.2, `vectorflow:bootstrap:operator` authorizes identity's one-time
first-admin operator delivery. It is valid only for the `vectorflow` audience,
with `sub` and `azp` both `veltro-identity` and no actor claims, including null
actor fields. The scope implies no other scope. HS256 compatibility tokens
cannot mint or verify it. Receivers still provide the existing issuer,
generation, public key ring and replay consumer.

`verify_authority_envelope_v2` verifies and consumes short-lived ES256
`veltro-suite-service+jwt` envelopes. The receiver supplies the exact issuer,
exact audience, active generation, that audience's public P-256 JWK ring, required
scope, and an atomic synchronous or asynchronous replay consumer. The consumer
runs exactly once after all stateless checks and must return literal `True`.

This package deliberately provides no v2 minting/signing API, private-key type,
key generator, JWKS/network fetcher, settings/environment adapter, or consumer
runtime wiring. Existing HS256 v1 compatibility remains separate and unchanged.

Actor envelopes may also carry `actor_sub` (identity's subject for the person,
a lowercase uuid) and the pair `actor_scope_kind`/`actor_team_id` (the grant the
exchange picked: `realm` with a null team, or `team` with a team id). They're
only valid next to the actor tuple. The verifier returns all three, as `None`
when the token leaves them out, so a product can resolve the actor by subject
first and fall back to email for older tokens.

## Account-section write

From 3.1.0, `chad:peer:account:write` and `warden:peer:account:write` are
valid scopes. Identity mints them when a person saves their own CHAD or
Warden section of Settings > Account (veltro#1411). Before that, saves rode on
the read-named `<product>:peer:status:read` (veltro#1211). Each grants only itself, so it
doesn't satisfy a `peer:status:read` check and a status token doesn't satisfy
it. Like `chad:alerts:write`, an envelope carrying either must have an actor,
so an actorless one is refused with `V2_INVALID_ACTOR`. VectorFlow has no
account section and no such scope.

To keep accepting saves from an older identity that sends `peer:status:read`,
a product can accept both by verifying with
`required_scope` set to the account write and, only on
`V2_INSUFFICIENT_SCOPE`, verifying again with the status read. The scope check
runs before the replay consumer, so the first attempt doesn't spend the jti.

## Product grant read

`product_grants_path(subject=None)` builds the path for identity's
`GET /api/authority/grants`, and `parse_product_grant_list(body, product=...,
subject=None)` checks the response strictly: the right product, canonical
subjects, native roles, a team id exactly when the grant is team scoped, and at
most the one requested subject. Bad bodies raise `SuiteAuthError` with
`GRANTS_INVALID_RESPONSE`. The product makes the HTTP call itself with its
workload credential; this package does no network I/O.

## Browser request assertion verifier

From 2.6.1, duplicate member names are checked per JSON object, so a nested
object (a team entry's `role` beside the grant's `role`) is no longer refused.
Older verifiers refuse any assertion that carries the grant's `teams` list.

`verify_browser_request_assertion` verifies and consumes short-lived ES256
`veltro-browser-request+jwt` request assertions minted by Veltro identity. The
receiver supplies the exact issuer, exact audience, active generation, that
audience's public P-256 JWK ring, the request being authorized (`request` with
`method` and `path`), and an atomic synchronous or asynchronous replay consumer.

The verifier enforces every binding the mint records: exact `typ`, `alg=ES256`
allowlist, audience key ring and `kid`, signature, issuer/audience, active
generation, nbf/iat/expiry capped at 60s, fixed realm `default`, grant-product
consistency, and — the point of the artifact — that the signed method and
canonical path match the request being authorized, using the same shared
`normalize_request_path` contract the mint uses. An assertion minted for
`GET /chad/api/alerts` never authorizes `POST /chad/api/rules`.

One-use semantics are the receiver's: after all stateless checks, the verifier
calls the replay consumer exactly once with a frozen `{issuer, audience,
generation, jti, expires_at}` tuple. The consumer must return literal `True`
only if it has not previously seen that tuple; a replayed `jti` is rejected when
the consumer returns `False`. The consumer must persist at least
`{issuer, audience, generation, jti}` until `expires_at` to enforce one-use
semantics across the token's validity window.

This package deliberately provides no request-assertion minting/signing API,
private-key type, key generator, JWKS/network fetcher, settings/environment
adapter, or consumer runtime wiring.

## Session team pick

From 3.0.0, a session's `selectedTeamId` is kept only when it matches the chrome
manifest's team id shape, `^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$`, and is
null otherwise. Nothing is trimmed. The TS and Python decoders share the rule
and the `session-v3` vectors that pin it.
