63 lines
4.5 KiB
Markdown
63 lines
4.5 KiB
Markdown
# Machine identity contract v1
|
|
|
|
`yovision.machine-identity/v1` defines service-to-service identity for YoVision connectors. It is deliberately separate from Sense and Bell users, GoAdmin JWT/Cookie state, database roles and operating-system accounts.
|
|
|
|
## Authentication mechanism
|
|
|
|
Every request uses HTTPS and one compact Ed25519 JWS in `Authorization: Bearer <token>`. The protected header is closed and contains `alg=EdDSA`, `typ=YOVISION-MACHINE+JWT`, `kid` and `ver=yovision.machine-identity/v1`. The closed claims object contains:
|
|
|
|
mTLS is not the primary v1 identity mechanism. A customer PKI may add mTLS later as transport hardening, but it cannot replace or weaken the v1 principal, audience, scope, request binding, replay and revocation checks.
|
|
|
|
- one instance-specific `iss`/`sub` principal;
|
|
- one exact service `aud`;
|
|
- the minimum required `scope` values;
|
|
- `iat`, `nbf`, `exp` and a single-use random `jti`;
|
|
- uppercase HTTP method `htm`, normalized absolute-path reference `htu`, and lowercase SHA-256 `body_sha256`.
|
|
|
|
Tokens live for at most 300 seconds. Consumers allow at most 30 seconds of clock skew, verify the signature and active key/principal before authorization, then atomically consume `jti` until `exp + skew`. Retrying transport creates a new token and `jti`; business idempotency keys remain unchanged.
|
|
|
|
Production consumers persist the replay key `(principal, jti)` in their own durable store so a process restart cannot reopen the replay window. The checked-in process-local replay stores are adapter test/default primitives only; connector tasks must inject an atomic durable implementation and test restart behavior without sharing a database across products.
|
|
|
|
The v1 scopes are:
|
|
|
|
| Caller | Audience | Scope |
|
|
|---|---|---|
|
|
| Sense | `yovision-brain` | `source-config:write` |
|
|
| Brain | `yovision-sense` | `runtime-status:write` |
|
|
| Brain or Sense | `yovision-bell` | `events:ingest` |
|
|
| Bell | `yovision-sense` | `evidence:read` |
|
|
|
|
No wildcard audience or scope exists. A relay authenticates as its own transport principal and never replaces the original event producer identity.
|
|
|
|
## Key lifecycle
|
|
|
|
Private Ed25519 keys are generated per product instance and stored outside the repository in an OS-protected file or secret store. Runtime configuration contains only the private-key path. Public registries are local consumer configuration, not a shared database.
|
|
|
|
Rotation first registers a new `kid`, switches the caller, and removes the old key after an overlap no longer than 24 hours. A disabled principal or revoked `kid` is rejected on every request, including tokens that have not expired. Emergency rollback disables the connector; it never enables a shared password, browser token, query token, plaintext transport or signature bypass.
|
|
|
|
## Threat boundary
|
|
|
|
v1 protects against token modification, wrong audience/scope, expired or premature tokens, captured-token replay, key/principal revocation and accidental credential mixing. It does not protect a host after administrator/root compromise, a stolen usable private key before revocation, compromised TLS trust roots, endpoint implementation flaws or denial of service. Rate and body-size limits remain consumer responsibilities.
|
|
|
|
See `../transport/v1/README.md` for HTTPS and request policy. Stable failures are defined in `errors.md`; callers and logs must expose only the stable code, principal/kid when already authenticated, and correlation ID—never the token, signature, private/public key material or complete Authorization header.
|
|
|
|
## Compatibility
|
|
|
|
v1 is closed. New optional claims require all consumers to accept them before producers emit them. Any change to signing input, algorithm, claim meaning, replay semantics, maximum lifetime, audience or scope meaning publishes a new major version. Consumers keep the last accepted major during a controlled migration; rollback disables the new producer version without weakening verification.
|
|
|
|
## Reproducible verification
|
|
|
|
From the repository root:
|
|
|
|
```powershell
|
|
pwsh -NoProfile -File contracts/tests/machine-identity-v1/run.ps1
|
|
|
|
cd Sense/server
|
|
go test -race ./app/sense/integration/machine_identity
|
|
|
|
cd ../../Bell/server
|
|
go test -race ./app/bell/integration/machine_identity
|
|
```
|
|
|
|
The isolated contract test validates both JSON Schemas, the fixed Go/Python Ed25519 vector, request binding, exact audience/scope, expiry, replay, rotation overlap, revocation, bearer-only extraction and verified TLS policy. Product connector tasks remain responsible for injecting a durable replay store and testing restart recovery.
|