feat(protocol): define native session credentials
Verify Protocol / module (push) Successful in 1m13s
Verify Protocol / verify (push) Successful in 35s

This commit is contained in:
sechmachine
2026-08-11 18:38:19 +07:00
parent 79d9e49497
commit afcd5d99db
32 changed files with 1565 additions and 149 deletions
@@ -0,0 +1,56 @@
# native-session-tunnel-credentials Specification
## Purpose
Define server-owned native session identity and short-lived tunnel credential disclosure without accepting client-owned policy.
## Requirements
### Requirement: Client-owned allocation policy is removed by a coordinated wire-version cutover
Control wire version `2` SHALL be current, wire version `1` SHALL be n-1, wire version `0` SHALL be n-2, and `control.v2` SHALL identify the current control feature. The wire-version-2 `SessionRequest` MUST reject `policy_snapshot`; `BrokerSession` SHALL retain the Server-owned policy snapshot disclosure. This removal is intentionally incompatible with the wire-version-1 request shape and SHALL require coordinated Protocol, Server, Data Plane, and client pin updates. Declaring wire version `1` as n-1 does not permit a wire-version-1 request body to be decoded as wire version `2`.
#### Scenario: Client attempts to supply policy
- **WHEN** a session request contains `policy_snapshot`
- **THEN** strict Protocol decoding rejects the unknown field
#### Scenario: A legacy client presents a wire-version-1 request shape
- **WHEN** a client uses the removed client-owned policy field or does not negotiate `control.v2`
- **THEN** the wire-version-2 broker request path rejects the request instead of silently interpreting it as compatible
### Requirement: Authentication response shapes are route-specific
Browser login and browser session responses SHALL use `BrowserAuthenticatedSession`, which forbids `native_identity`. Native bearer session responses SHALL use `NativeAuthenticatedSession`, which requires a `NativeSessionIdentity` containing both `client_device_id` and `device_key_id`. Both response types SHALL require every `roles` item to contain 1 through 64 UTF-8 bytes.
#### Scenario: Native identity is incomplete
- **WHEN** a native session response omits either identity field
- **THEN** strict Protocol decoding rejects the nested object
#### Scenario: Browser response leaks native identity
- **WHEN** a browser login or browser session response contains `native_identity`
- **THEN** strict Protocol decoding rejects the response
#### Scenario: Authentication response has a malformed role
- **WHEN** any `roles` item is empty or exceeds 64 UTF-8 bytes
- **THEN** every generated binding rejects the response
### Requirement: Native tunnel credentials are non-cacheable
`POST /api/v1/auth/tunnel-credentials` SHALL accept only native bearer authentication, no request body, and return a bounded `NativeTunnelCredential` with `Cache-Control: no-store`. `NativeTunnelCredential.expires_at` SHALL be canonical RFC 3339 UTC in every generated binding: an uppercase `T`, a `Z` suffix, and either no fractional seconds or a 1-through-9-digit non-zero-terminated fractional component.
#### Scenario: Native client requests tunnel credentials
- **WHEN** an authenticated native client calls the endpoint
- **THEN** the response identifies the client device and key, supplies certificate and trust PEM, gives an expiry, and cannot be stored
#### Scenario: Native tunnel credential uses a noncanonical expiry
- **WHEN** `expires_at` uses a numeric offset or a noncanonical fractional representation
- **THEN** every generated binding rejects the credential
### Requirement: Swift bindings support the macOS client deployment floor
The generated Swift package SHALL declare macOS 14 as its minimum supported macOS platform.
#### Scenario: Native client consumes the Swift package
- **WHEN** the package manifest is resolved for the Phase 3D macOS client
- **THEN** its platform declaration permits macOS 14 and later
### Requirement: Manifest public identity is the TLS server name
`ConnectionManifest.gateway.public_identity` SHALL be the exact TLS server name and SHALL remain distinct from dial addresses, gateway UUIDs, certificate fingerprints, and provider identities.
#### Scenario: Client connects to a gateway address
- **WHEN** a client dials any advertised gateway address
- **THEN** it verifies TLS against `gateway.public_identity`