Skip to content

Commit 451a2fc

Browse files
committed
docs: record shared API credential boundaries for every product
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
1 parent c5c1e37 commit 451a2fc

8 files changed

Lines changed: 204 additions & 2 deletions

File tree

‎crates/registry-cli-api/README.md‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,54 @@ check output uses the shared `PlatformCliConnectionCheckReport` contract in
2222
with [example/connection-check-report.json](example/connection-check-report.json)
2323
as its maintained example.
2424

25+
## Security boundary
26+
27+
Connection selection does not create product authority. `--client` delegates
28+
to the product adapter, which owns any retained local endpoint, credential,
29+
profile headers, and readiness checks. `--connection` materializes one saved
30+
connection for that product, and `--url` is an advanced one-off destination
31+
that is anonymous unless `--token-file` is supplied. Saved authentication is
32+
exactly one of anonymous, a referenced bearer, or `private_key_jwt`. The
33+
receiving product still authenticates and authorizes every protected request.
34+
35+
The direct `--token-file` input must fit within 8 KiB, including its optional
36+
line ending. That ending is removed and the bearer remains opaque; it need not
37+
be a compact JWT. Direct token,
38+
CA, request-body, and header files use the shared bounded regular-file reader;
39+
on Unix it opens nonblocking, so a FIFO is refused instead of hanging. A
40+
symlink whose target is a regular file remains accepted. Only `--input -`
41+
reads a request body from standard input. The saved-connections document uses
42+
the same reader under its own document bound. Saved bearer and private-key
43+
references instead use the platform secret resolver, retaining that resolver's
44+
separate root, permission, size, and symlink policy.
45+
46+
Every service base URL uses the shared checked HTTP(S) type, which permits
47+
plain HTTP only for loopback. A request path stays under the selected origin
48+
and deployment prefix. The selected connection owns `Host`, automatic
49+
`Authorization`, and any product profile header it sets, so command-line headers
50+
cannot replace them. The client ignores ambient proxies, follows no redirect,
51+
retries no request, applies fixed connect and overall deadlines, and bounds
52+
both request and response bodies. Debug output and transport errors do not
53+
contain the bearer or request values.
54+
55+
The maintained proofs are:
56+
57+
- `crates/registry-cli-api/tests/api_http.rs`, including
58+
`automatic_credentials_cannot_be_replaced_by_a_repeated_header`,
59+
`paths_and_host_headers_cannot_escape_the_selected_endpoint`,
60+
`redirect_answers_are_returned_without_following_them`,
61+
`response_bodies_are_bounded`, and
62+
`bearer_connection_debug_and_failures_do_not_disclose_the_token`;
63+
- `crates/registry-cli-api/tests/connection_store.rs`,
64+
`saved_connections_add_show_use_reread_credentials_and_acquire_private_key_jwt`;
65+
- `crates/registry-bregctl/tests/api_cli.rs`,
66+
`raw_api_refuses_fifo_file_inputs_without_blocking`,
67+
`connection_commands_refuse_fifo_stores_without_blocking`, and
68+
`raw_api_accepts_a_regular_token_file_and_request_body_from_standard_input`.
69+
70+
These references identify the maintained contract; this README does not claim
71+
that they ran in a particular review.
72+
2573
Run the focused checks from the workspace root:
2674

2775
```console

‎products/breg/SECURITY-REVIEW-NOTES.md‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4588,3 +4588,33 @@ traceability catalog records these proofs without claiming an execution run.
45884588
- The route reads the known Proposal's Action identifier before body parsing so
45894589
it can attribute an admitted refusal. It releases no Proposal or context
45904590
values during that lookup or refusal.
4591+
4592+
## Raw API caller credentials
4593+
4594+
### Threat
4595+
4596+
A local raw API request uses a client registered for another resource, or the
4597+
tooling's bearer and endpoint selection is mistaken for BReg authorization.
4598+
4599+
### Enforcement and defaults
4600+
4601+
`bregctl api PATH --client CLIENT` requires a ready local development session,
4602+
selects only a client admitted to that BReg resource, obtains a fresh bearer
4603+
for the client's registered resource and scopes, and keeps it in memory. The
4604+
adapter uses the API origin retained by that session and creates no reusable
4605+
header file. A saved or explicit remote connection instead uses the endpoint
4606+
and authentication the operator selected. Both paths use the
4607+
[`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary).
4608+
4609+
The helper adds no BReg grant. The runtime still verifies the credential,
4610+
resolves the configured access profile, and authorizes the requested route,
4611+
record, fields, and operation.
4612+
4613+
### Tests
4614+
4615+
- `crates/registry-bregctl/src/dev/tests.rs`:
4616+
`local_api_accepts_only_clients_admitted_to_this_breg_resource`.
4617+
- The shared transport, saved-credential, and process tests named in the
4618+
`registry-cli-api` security boundary.
4619+
4620+
These are maintained test references, not claims of execution in this note.

‎products/casework/SECURITY-REVIEW-NOTES.md‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,3 +1123,29 @@ worker iteration that fails, such as a finish refused under a replaced lease,
11231123
is logged without the row's `event_id` and `destination_id`, because the
11241124
dispatch core reports it without its row. Dispatch operational events are not
11251125
audited.
1126+
1127+
## Raw API caller credentials and profiles
1128+
1129+
Threat: a local diagnostic request presents one client's bearer with another
1130+
client's Casework or Review profile, or treats a profile header as authority
1131+
independent of runtime authorization.
1132+
1133+
`caseworkctl api PATH --client CLIENT` requires a ready local development
1134+
session. Its adapter selects the exact retained client and profile, obtains a
1135+
fresh bearer for that client, and binds the same profile into the
1136+
`Registry-Casework-Profile` and `Registry-Review-Profile` headers. The selected
1137+
connection owns those headers and `Authorization`, so raw command-line headers
1138+
cannot replace them. An integration client registered for another resource is
1139+
refused. Saved and explicit remote connections remain operator-selected and
1140+
follow the shared
1141+
[`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary).
1142+
1143+
The tooling adds no queue, source, review, or task authority. Casework still
1144+
authenticates the bearer, resolves the applicable caller policy, and decides
1145+
each protected route. The maintained proofs are
1146+
`api_client_selects_the_exact_retained_profile_and_refuses_unknown_clients`,
1147+
`api_connection_sends_the_bearer_profiles_and_writes_only_response_bytes`, and
1148+
`local_api_refuses_an_integration_client_bound_to_another_resource` in
1149+
`crates/registry-caseworkctl/src/dev/tests.rs`, plus the shared tests named in
1150+
the `registry-cli-api` README. This note records their obligations, not an
1151+
execution result.

‎products/coordinator/SECURITY-REVIEW-NOTES.md‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,50 @@ value-free diagnostics remain unchanged. This check applies only to
8080
filesystem and directory-component races remain accepted for this adopter
8181
CLI rather than introducing a directory-descriptor traversal policy.
8282

83+
## Raw API connection authentication
84+
85+
### Threat
86+
87+
An operator assumes the raw API command reuses the legacy Coordinator token
88+
reader, or assumes a saved bearer or `private_key_jwt` connection grants
89+
workflow authority by itself.
90+
91+
### Enforcement and defaults
92+
93+
Coordinator retains no local caller session, so `coordinatorctl api` refuses
94+
`--client`. The operator selects a saved connection or an explicit one-off
95+
URL. Saved authentication is exactly one of anonymous, a referenced opaque
96+
bearer, or renewable `private_key_jwt`, under the shared
97+
[`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary).
98+
The helper confines the destination and headers, acquires the selected
99+
credential, and releases only the raw bounded response. It carries no caller
100+
policy, workflow, run ownership, or downstream product authority. Coordinator
101+
still authenticates and authorizes each protected route, and every receiving
102+
product still decides an effect requested by a run.
103+
104+
This path deliberately does not reuse the legacy reader described above.
105+
Legacy authenticated Coordinator commands keep their 16,384-byte compact-JWT
106+
validation and, on Unix, `NOFOLLOW` token open. Direct
107+
`api --url --token-file` instead uses the shared opaque-bearer contract: at
108+
most 8 KiB and a symlink to a regular file is accepted. Saved bearer and
109+
private-key references use the platform secret resolver's separate strict
110+
file policy. These differences preserve both existing contracts rather than
111+
silently changing older commands.
112+
113+
### Tests
114+
115+
- `crates/registry-coordinator/tests/api_cli.rs`:
116+
`api_and_saved_connections_are_available_without_a_runtime_config` and
117+
`raw_api_refuses_report_format_before_network_access`.
118+
- The shared saved-credential, transport, regular-file, and process tests
119+
named in the `registry-cli-api` security boundary.
120+
- The legacy reader remains pinned by
121+
`token_file_refuses_symlinks_and_fifos_without_blocking` and
122+
`a_relative_token_file_is_read_from_the_current_directory` in
123+
`crates/registry-coordinator/tests/cli_remote.rs`.
124+
125+
These are maintained references, not claims that the tests ran in this note.
126+
83127
## OIDC issuer transport and private addresses
84128

85129
### Threat

‎products/discovery/README.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ traceability. The normal operator flow, owned by `discoveryctl`, is offline
4141
then restart. The runtime verifies `SHA256SUMS` and an optional
4242
`package.expectedDigest` pin before consuming the exact packaged index bytes.
4343

44+
`discoveryctl api` has no local `--client` credential adapter. Discovery's
45+
endpoint is public, so the product resolver directs operators to an anonymous
46+
saved connection. The shared CLI also permits an operator to deliberately
47+
select an explicit or saved authenticated connection, but that credential is
48+
operator-supplied transport state: it is never derived from catalog metadata,
49+
creates no Discovery authority, and does not make Discovery a native-provider
50+
proxy. Endpoint and request handling follow the shared
51+
[`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary).
52+
`api_and_saved_connections_are_available_without_a_runtime_config` in
53+
`crates/registry-discoveryctl/tests/api_cli.rs` pins the product surface; the
54+
shared README names the transport and credential tests. These are maintained
55+
references, not claims of execution here.
56+
4457
## Independent release installation
4558

4659
For a published Discovery unit release, download its `discovery-vX.Y.Z-install.sh`

‎products/evidence/README.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,24 @@ before the response exists. Stop and clean with `dev stop` and `dev clean`.
105105
An explicitly configured shared issuer can be selected with `--issuer-project`;
106106
Evidence still verifies its own clients, resources, scopes and complete grants.
107107

108+
`evidencectl api PATH --client CLIENT` reuses that ready local session without
109+
writing the tutorial bearer header. It resolves the exact registered client
110+
against the retained access-profile digests, obtains a fresh short-lived token
111+
with the client's retained private key, and sends it only to the Evidence
112+
origin in the validated ready state. A saved or explicit remote connection is
113+
operator-selected. Both follow the shared
114+
[`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary),
115+
which supplies transport and credentials but no Evidence authority. The
116+
runtime still decides authentication, complete-grant authorization, selector
117+
minimization, audit, and disclosure.
118+
119+
`ready_and_stopped_handoffs_validate_the_closed_lifecycle_state` in
120+
`crates/registry-evidencectl/src/dev.rs` pins the ready-state handoff, and
121+
`raw_api_response_bypasses_the_ctl_report_envelope` in
122+
`crates/registry-evidencectl/tests/api_cli.rs` pins the product command's raw
123+
response path. The shared README names the transport and credential tests.
124+
These are maintained references, not claims of execution here.
125+
108126
Source descriptions accept HTTPS or numeric loopback HTTP and reject embedded
109127
credentials, queries and fragments. Fetch an authenticated API description with
110128
your own client and pass its local file. Source credentials grant no Evidence

‎products/messaging/SECURITY-REVIEW-NOTES.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,8 +1011,9 @@ client-token acquisition path, but keeps the token in the request connection
10111011
instead of publishing a header file. It requires a ready development session
10121012
and takes its destination only from the exact nonzero
10131013
`http://127.0.0.1:PORT` API origin retained in the typed session record. The
1014-
shared CLI API transport appends only a relative path without changing that
1015-
origin or its deployment prefix, owns the `Host` and automatic
1014+
shared [`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary)
1015+
appends only a relative path without changing that origin or its deployment
1016+
prefix, owns the `Host` and automatic
10161017
`Authorization` headers, follows no redirects, and ignores ambient proxy
10171018
settings. The Messaging runtime still authenticates the token and applies its
10181019
ordinary access-profile and operation authorization on every protected route;

‎products/scheduling/SECURITY-REVIEW-NOTES.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,3 +1493,25 @@ remaining focused proofs and does not assert that they ran.
14931493
- Detail readers receive the current attendance observation with the ordinary
14941494
appointment document. Operational readers receive it only when their profile
14951495
explicitly selects attendance.
1496+
1497+
## Raw API connection authentication
1498+
1499+
Threat: a generic diagnostic command is mistaken for Scheduling authority, or
1500+
a credential selected for one connection is silently replaced on the request.
1501+
1502+
Scheduling retains no local caller session, so `schedulingctl api` does not
1503+
resolve `--client`. The operator selects a saved connection or an explicit
1504+
one-off URL. A saved connection may be anonymous, a referenced bearer, or a
1505+
renewable `private_key_jwt` client under the shared
1506+
[`registry-cli-api` security boundary](../../crates/registry-cli-api/README.md#security-boundary).
1507+
That boundary owns endpoint confinement, automatic authorization, credential
1508+
resolution, redirects, proxies, bounds, and redaction; it carries no task
1509+
grant, catalogue scope, appointment ownership, or capacity authority.
1510+
1511+
The runtime continues to authenticate and authorize every protected request.
1512+
An anonymous connection reaches only routes the runtime already makes public.
1513+
`api_and_saved_connections_are_available_without_a_runtime_config` and
1514+
`raw_api_refuses_report_format_before_network_access` in
1515+
`crates/registry-schedulingctl/tests/api_cli.rs` pin the product surface. The
1516+
shared README names the saved bearer, `private_key_jwt`, and transport proofs.
1517+
These references do not assert an execution run here.

0 commit comments

Comments
 (0)