aac-cli 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {aac_cli-0.2.0/aac_cli.egg-info → aac_cli-0.2.2}/PKG-INFO +225 -41
  2. {aac_cli-0.2.0 → aac_cli-0.2.2}/README.md +224 -40
  3. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/__init__.py +1 -1
  4. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/agent_cli.py +17 -8
  5. aac_cli-0.2.2/aac_cli/agent_config.py +462 -0
  6. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/agent_layout.py +8 -6
  7. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/agent_record.py +26 -5
  8. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/cli.py +58 -4
  9. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/config_render.py +69 -54
  10. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/dev_material.py +31 -16
  11. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/init_cli.py +116 -33
  12. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/material_cases.py +3 -3
  13. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/supplied_material.py +4 -4
  14. {aac_cli-0.2.0 → aac_cli-0.2.2/aac_cli.egg-info}/PKG-INFO +225 -41
  15. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli.egg-info/SOURCES.txt +1 -0
  16. {aac_cli-0.2.0 → aac_cli-0.2.2}/pyproject.toml +2 -2
  17. {aac_cli-0.2.0 → aac_cli-0.2.2}/LICENSE +0 -0
  18. {aac_cli-0.2.0 → aac_cli-0.2.2}/MANIFEST.in +0 -0
  19. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/__main__.py +0 -0
  20. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/admin_key_pem.py +0 -0
  21. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/agent_health.py +0 -0
  22. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/api_key_rotation_state.py +0 -0
  23. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/config.py +0 -0
  24. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/idp_recovery.py +0 -0
  25. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/profiles.py +0 -0
  26. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/reference.py +0 -0
  27. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/registration_state.py +0 -0
  28. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/secure_files.py +0 -0
  29. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli/sso_login.py +0 -0
  30. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli.egg-info/dependency_links.txt +0 -0
  31. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli.egg-info/entry_points.txt +0 -0
  32. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli.egg-info/requires.txt +0 -0
  33. {aac_cli-0.2.0 → aac_cli-0.2.2}/aac_cli.egg-info/top_level.txt +0 -0
  34. {aac_cli-0.2.0 → aac_cli-0.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aac-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: The aac platform CLI — headless operator interface to the AAC control plane (tenant registration, chain audit).
5
5
  Author: Agent Authority Cloud Project
6
6
  License-Expression: Apache-2.0
@@ -24,6 +24,9 @@ which tenant they belong to and what they were authorised to do. A
24
24
  runs beside an AAC sidecar that signs outgoing requests and verifies
25
25
  incoming ones against public trust material the tenant publishes.
26
26
 
27
+ New to AAC? [What AAC is for](https://cascadeauth.github.io/aac-sidecar-go/#what-aac-is-for)
28
+ explains what delegated authority between agents buys you, and what it does not.
29
+
27
30
  The `aac` command is how a tenant's operator does everything that is not
28
31
  done by the sidecar itself: register the tenant, sign in, manage keys,
29
32
  workloads and domains, and prepare a runnable local workload. Everything
@@ -60,20 +63,21 @@ Python 3.10 or newer is required.
60
63
  registers the agent's identity with AAC and creates the keys, certificates
61
64
  and configuration its sidecar needs. The agent itself is yours. The first
62
65
  run also creates your profile and registers your tenant; run it again with
63
- a new `--agent` and `--workload-path`, and the same `--trust-url` and
64
- `--idp`, for each further agent.
66
+ a new `--agent` and its own `--agent-config` file, and the same `--trust-url`
67
+ and `--idp`, for each further agent.
65
68
 
66
69
  Along the way it signs you in, registers a developer tenant (or reuses the
67
70
  one your profile is already bound to), takes the trust domain AAC assigns to the
68
- tenant, registers a sample workload, generates development keys and
71
+ tenant, registers your workload, generates development keys and
69
72
  certificates, and writes a complete sidecar configuration together with the
70
73
  files the trust-anchor publisher and Docker Compose need.
71
74
 
72
75
  Point it at the endpoints your AAC environment gives you. The example below
73
- uses the AAC stage environment:
76
+ uses the AAC stage environment. First save the YAML example in “Agent configuration”
77
+ below as `orders.yaml`:
74
78
 
75
79
  ```bash
76
- aac init --profile stage \
80
+ aac init --profile stage --agent orders --agent-config orders.yaml \
77
81
  --admin-url https://api.stage.cascadeauth.dev \
78
82
  --data-plane-url https://api.stage.cascadeauth.dev \
79
83
  --trust-url https://trust.stage.cascadeauth.dev \
@@ -85,7 +89,7 @@ tenant, because a tenant is permanent. In a script, where there is no
85
89
  terminal to answer the question, pass `--create-tenant`:
86
90
 
87
91
  ```bash
88
- aac init --profile stage \
92
+ aac init --profile stage --agent orders --agent-config orders.yaml \
89
93
  --admin-url https://api.stage.cascadeauth.dev \
90
94
  --data-plane-url https://api.stage.cascadeauth.dev \
91
95
  --trust-url https://trust.stage.cascadeauth.dev \
@@ -117,8 +121,7 @@ never asks you to pick between GitHub and Google again.
117
121
 
118
122
  ### What it creates, and where
119
123
 
120
- * `~/.aac/agents/<agent>/` holds the files **one sidecar** needs (default
121
- name `starter`), in folders named for where each file goes. `sidecar/` is
124
+ * `~/.aac/agents/<agent>/` holds the files **one sidecar** needs, in folders named for where each file goes. `sidecar/` is
122
125
  what you mount or copy into the sidecar: the workload, receipt and HTTPS
123
126
  key pairs, this agent's root-signing key, the CA certificate and the
124
127
  outbound CA bundle. `agent/` is what the paired application reads: the
@@ -153,23 +156,27 @@ settings files written for them. It also records how far setup got, so
153
156
  rerunning `aac init` resumes where it stopped.
154
157
 
155
158
  Use one agent per workload. `aac init --agent <name>` creates an agent
156
- (with `--trust-url`) or resumes it (the default name is `starter`), and
159
+ (with `--agent-config` and `--trust-url`) or resumes it. There is no default agent;
157
160
  three commands look after it:
158
161
 
159
162
  ```bash
160
- aac agent status --agent starter # what exists, what is due, and the next step
161
- aac agent renew --agent starter # replace the short-lived certificates
163
+ aac agent status --agent orders # what exists, what is due, and the next step
164
+ aac agent renew --agent orders # replace the short-lived certificates
162
165
  aac agent list # every agent on this machine
163
166
  ```
164
167
 
168
+ `agent list` reports an unreadable or unsupported record in that agent's
169
+ `state` and continues listing the others. `agent status --agent <name>` still
170
+ returns a local-state error for that individual agent.
171
+
165
172
  There is no separate command for the settings files. Running setup again —
166
173
  with the profile the agent belongs to — writes `sidecar-config.yaml`,
167
174
  `compose.env` and the tenant's `publisher.env` from what the agent already
168
175
  records, without touching a single key:
169
176
 
170
177
  ```bash
171
- aac init --profile stage --agent starter # write them again
172
- aac init --profile stage --agent starter --layout container # and change the layout
178
+ aac init --profile stage --agent orders # write them again
179
+ aac init --profile stage --agent orders --layout container # and change the layout
173
180
  ```
174
181
 
175
182
  That is how you rebuild a settings file you lost and how you move between
@@ -181,7 +188,7 @@ whenever it is the next step.
181
188
  A second workload is a second agent with its own workload path:
182
189
 
183
190
  ```bash
184
- aac init --profile stage --agent worker --workload-path demo/worker \
191
+ aac init --profile stage --agent worker --agent-config worker.yaml \
185
192
  --idp github --trust-url https://trust.stage.cascadeauth.dev
186
193
  ```
187
194
 
@@ -192,14 +199,177 @@ settings files never changes that file's endpoints, so an agent created with
192
199
  a different trust URL stops at its last step and has to be set up again
193
200
  under a new name.
194
201
 
195
- `--agent` names the local files; `--workload-path` chooses the workload's
196
- identity, the path at the end of its SPIFFE ID (`demo/agent` unless you
197
- choose another). Two agents with the same workload path are the same
202
+ `--agent` names the local files and must match the file's `agent_name`.
203
+ The file's required `workload_path` supplies the path at the end of the SPIFFE ID.
204
+ An optional `--workload-path` must match the file or saved identity; omission
205
+ on refresh reuses that identity. Missing or conflicting identities are refused. Two agents with the same workload path are the same
198
206
  workload holding different keys: that is what a replacement computer wants,
199
207
  and what a second workload does not. The agent name is permanent, because
200
208
  the root key id is made from it. `aac init` needs the profile the agent was
201
209
  created with; the `aac agent` commands read it from the agent itself.
202
210
 
211
+ ### Agent configuration
212
+
213
+ The operator writes one YAML file. `aac init --agent-config PATH` validates and
214
+ explicitly applies it. The profile remains INI; this file describes one agent,
215
+ not its profile or the hosted service. For example, save this as `orders.yaml`:
216
+
217
+ ```yaml
218
+ agent_name: orders
219
+ workload_path: fulfilment/orders
220
+ tls_server_names: [orders.internal.example, localhost, 127.0.0.1]
221
+ sidecar:
222
+ agent_invoke_url: http://127.0.0.1:8000/invoke
223
+ external_bind_address: 127.0.0.1
224
+ telemetry:
225
+ sink: orders.jsonl
226
+ central_forward: false
227
+ classes_of_action:
228
+ fulfil_order:
229
+ predicates:
230
+ action: reserve_inventory
231
+ amount_max: 10000
232
+ originator_reference: "PO #4143"
233
+ valid_for: +8m
234
+ destinations: {}
235
+ ```
236
+
237
+ This declares the tenant's permission; AAC does not invent one. The application
238
+ chooses `fulfil_order` when starting a chain and checks that its business action
239
+ matches the authorized context. Units and business meaning belong to the
240
+ application. Empty classes and destinations are allowed for registration before
241
+ peer identities are known. No self destination is added.
242
+
243
+ **Chain-start boundary:** restrict `/v1/agent/delegations` and
244
+ `/v1/agent/mint-root` to the authorized originating application at the
245
+ network/ingress boundary. Sidecar **v0.4.0 and later** also require the existing
246
+ pair's AAC1-HMAC-SHA256 signature over the exact alias and raw request body.
247
+ Older releases do not authenticate these callers, so sharing a private network
248
+ with peers is insufficient. An authorized separate originator may hold the pair
249
+ secret only inside the same trusted tenant-application boundary; it gains
250
+ callback-signing capability too. Never share secrets across pairs or tenants.
251
+ Pairing freshness is not idempotent chain creation; do not automatically retry
252
+ an uncertain mint. Development certificates do not require `dev_mode`.
253
+
254
+ Applications using v0.4.0 can supply per-request `obligations` for T1. Equal
255
+ configured/request values combine once; differing values refuse rather than
256
+ override or intersect. Put dynamic limits in the request instead of also
257
+ configuring a different class value. Native request `valid_until` is reserved;
258
+ remove it and use class `valid_for`. For signed correlation, normally supply a
259
+ `task_ref` obligation per request: top-level `task_ref` alone is correlation
260
+ metadata, while a static class predicate deliberately shares one convergence
261
+ key across that class's chains. Omitted/null metadata inherits a configured or
262
+ obligation predicate; an explicit conflicting value refuses before minting.
263
+
264
+ The following is the complete input schema. Unknown fields, duplicate mapping
265
+ keys, YAML aliases/merge keys, object tags and files over 64 KiB are refused.
266
+ Null is not an omitted value. Strings must be nonempty and have no surrounding
267
+ whitespace or control characters. Lists allow at most 128 unique values; class
268
+ and destination maps allow at most 128 entries each.
269
+
270
+ | Field | Type and meaning | Default when omitted |
271
+ |---|---|---|
272
+ | `agent_name` | Required local name, 3–15 characters under the same name rules as `--agent`; must match it. | None |
273
+ | `workload_path` | Required concrete SPIFFE path, 3–150 ASCII characters; slash-separated letters/digits/`._~-`, no empty or dot segments, wildcard, query or escaped character. Fixed once the agent exists. | None |
274
+ | `tls_server_names` | Required nonempty list of DNS names/IP addresses callers use for HTTPS, including the originating application. No URLs, wildcards or unspecified bind addresses. | None |
275
+ | `sidecar.dev_mode` | Boolean enabling the runtime's development exceptions; independent of certificate source and replay profile. | `false` |
276
+ | `sidecar.loopback_bind_address` | Must be exactly `127.0.0.1` when `dev_mode: false`; another loopback IP address requires `dev_mode: true`. Non-loopback addresses are not accepted by this input. | `127.0.0.1` |
277
+ | `sidecar.external_bind_address` | IP bind address for the peer listener; choose the reachability your ingress allows. | `127.0.0.1` |
278
+ | `sidecar.loopback_port`, `sidecar.external_port` | Distinct integer ports, 1–65535. | `8080`, `9443` |
279
+ | `sidecar.agent_invoke_url` | Absolute HTTP(S) URL of your application's invoke endpoint. | `http://127.0.0.1:8000/invoke` |
280
+ | `sidecar.log_level` | `debug`, `info`, `warn` or `error`. | `info` |
281
+ | `sidecar.telemetry.sink` | Filename within managed `state/` (letters/digits/`_.-`, starting with a letter/digit), or `stdout` / `none`. `a2a-egress.db` is reserved for managed database state, regardless of case or whether A2A is enabled. Host/container paths are generated. | `telemetry.jsonl` |
282
+ | `sidecar.telemetry.central_forward` | Boolean opt-in for asynchronous metadata-only forwarding. The endpoint and tenant API-key file come from the selected profile/agent binding, never another tenant's file. | `false` |
283
+ | `replay_protection.backend` | `memory` or `valkey`. | `memory` |
284
+ | `replay_protection.deployment_profile` | `basic` with memory; `ha-retained-write-safe` with Valkey. No fallback. | The matching profile |
285
+ | `replay_protection.url` | Required absolute `valkeys://` URL for Valkey, with an optional numeric database path. No query, fragment or embedded credentials. Not valid with memory. | None |
286
+ | `replay_protection.memory_max_entries` | Integer 1–1000000. | `100000` |
287
+ | `replay_protection.connect_timeout_ms` | Integer 1–100. | Runtime default `100` |
288
+ | `replay_protection.operation_timeout_ms` | Integer 1–250. | Runtime default `50` |
289
+ | `replay_protection.max_connections` | Integer 1–4096. | Runtime default `32` |
290
+ | `replay_protection.cold_start_quarantine_seconds` | Integer 120–3600. | Runtime default `120` |
291
+ | `trust_anchors.tenant_ids` | Additional canonical `tnt-<UUID>` tenant IDs whose root signatures you trust. | Empty; own tenant is always included |
292
+ | `spiffe_bundles.trust_domains` | Additional lowercase trust domains whose workload certificates you trust. | Empty; own assigned domain is always included |
293
+ | `https_trust.ca_files` | Paths to public PEM CA certificate files, relative to the input file or absolute; up to 256 KiB each and 1 MiB total. Certificate-only PEM is saved; refresh/renewal do not reread the source files. No private keys. | Empty; own CA is always included |
294
+ | `https_trust.system_roots` | Boolean adding the current machine's system public HTTPS roots, with certifi fallback. With `false`, every outbound TLS service—including the control plane, trust URL, peer and Valkey—must chain to the own CA or a CA listed in `ca_files`. | `true` |
295
+ | `classes_of_action.<name>.predicates` | Mapping of registered predicate names to supported values, described below. The class entry's `<name>` uses letters/digits/`_.-`, starting with a letter/digit, up to 128 characters; predicate names come only from the closed registry. | Empty mapping |
296
+ | `classes_of_action.<name>.valid_for` | Required positive duration, 1 second–24 hours: digits with optional `+`, then `s`, `m`, `h` or `d`. The CLI supplies the registered `audience_self`. | None |
297
+ | `destinations.<name>.url` | Required absolute HTTPS recipient URL, for native receive or A2A. | None |
298
+ | `destinations.<name>.audience_pattern` | Required exact registered SPIFFE identity; no wildcard. | None |
299
+ | `destinations.<name>.predicates`, `.valid_for` | Same value/duration contract as classes. | Empty predicates; duration required |
300
+ | `destinations.<name>.timeout_ms` | Integer 1–2147483647 without A2A; 1–60000 for every destination when A2A is enabled, matching its generated deadline. | `10000` |
301
+ | `a2a.public_base_url`, `a2a.local_handler_url` | Optional A2A block; both required if present. Public URL is HTTPS with no path except optional `/`; the HTTP(S) local handler path must be exactly `/a2a/v1`, with no escaped spelling. Neither URL permits query or fragment markers, even empty ones. Managed A2A state paths and a 60-second deadline are generated. No A2A self-route is added. | A2A disabled |
302
+
303
+ URL hosts are ASCII DNS names or IP addresses; URL fields reject whitespace,
304
+ backslashes, embedded credentials and fragments. Basic replay history
305
+ is process-local: restarting loses it, and replicas do not share it. Selecting
306
+ Shared durable declares that the operator has qualified the Valkey service; the
307
+ CLI does not establish durability. This configuration interface does not accept
308
+ credential-bearing replay URLs.
309
+
310
+ The three kinds of trust above are separate checks. Obtain peer tenant IDs,
311
+ assigned trust domains and exact workload identities from their public status
312
+ or registration output. Exchange public CA certificates only. After registering
313
+ both agents, explicitly apply their peer configurations with the same command:
314
+
315
+ ```bash
316
+ aac init --profile stage --agent orders --agent-config orders.yaml
317
+ ```
318
+
319
+ The closed predicate registry accepts `action`, `amount_max`, `amount_min`,
320
+ `amount`, `valid_from`, `beneficiary_account`, `beneficiary_class`, `currency`,
321
+ `data_scope`, `purpose`, `human_authorization_class`, `task_ref`,
322
+ `min_account_age_days`, `max_authority_amount`, `assessed_damage_amount`,
323
+ `assessment_outcome`, `surveyor_findings`, `payout_amount`, `program_reference`,
324
+ `reporting_quarter`, `claim_ref`, `hours`, `quantity_units`, `beneficiary`,
325
+ `unit_price_usd`, `account`, `esg_scope3_co2e_kg`, `conflict_minerals_clear`,
326
+ `originator_reference`, `scope`, `composite_payout_amount`,
327
+ `composite_payout_total`, `composite_units_total`,
328
+ `composite_esg_scope3_co2e_kg_total` and `composite_conflict_minerals_clear`.
329
+ `amount_max`, `amount_min` and `valid_from` accept nonnegative integers or
330
+ canonical decimal strings (`0` or a nonzero digit followed by digits), at most
331
+ 9223372036854775807. Enforced numbers are checked before YAML integer conversion:
332
+ spellings such as `010`, `0x10`, `1_000` and `+10` are refused, quoted or unquoted,
333
+ so the loader cannot silently reinterpret a limit. Other values must be strings. Commas are refused because
334
+ they separate wire predicates. The combined mapping has a 7900-byte UTF-8
335
+ budget, leaving room for the generated expiry.
336
+
337
+ `valid_until` is generated authority data, so it is refused in static input:
338
+ use `valid_for`. Registry membership alone does not give business labels new
339
+ monotonic enforcement. The current HTTP mint route uses the selected class's
340
+ static first limits; it accepts no per-request obligations. Your application
341
+ remains responsible for its policy decision.
342
+
343
+ Applying a file rewrites the generated configuration; restart the sidecar to
344
+ load it. Ordinary refresh and certificate renewal use the saved accepted values,
345
+ even if the original file is edited, moved or removed. Public CA file changes
346
+ also require explicit reapplication. The source file is never rewritten. Keep
347
+ the agent directory, credentials and keys; the input file is not their backup.
348
+ Generated files are disposable outputs and should not be hand-edited.
349
+
350
+ HTTPS certificates must authenticate every configured connection name. The CLI
351
+ issues them for those names or checks supplied certificates against them; renewal
352
+ keeps those names. Applying a different name set requires the installed certificate
353
+ to cover it already: supplied issuers can issue a certificate covering both sets
354
+ before the change. A CLI-issued agent needing new names must be created under a
355
+ new name with the intended configuration. No old agent-record format is migrated.
356
+
357
+ Central forwarding retains the local sink and sends only permitted metadata.
358
+ It is asynchronous and best-effort; a local event does not prove central delivery.
359
+ It excludes business predicates, task references, raw tokens/proofs and receipts.
360
+ `AAC_TELEMETRY_SINK` and `AAC_AGENT_STATE_DIR` in `compose.env` identify the local
361
+ file and mount; `AAC_API_KEY_FILE` identifies this tenant's credential. Mount it
362
+ at `/run/secrets/tenant-api-key` in the container layout. Do not read private
363
+ `record.json` from consumers.
364
+
365
+ For a CA change: stop the affected sidecar/application; renew or install the
366
+ issuer's replacement certificates; restart the publisher and verify publication
367
+ with `aac agent status --agent <name> --remote`; exchange the new public CA with
368
+ each intended peer and explicitly reapply that peer's configuration; then restart
369
+ the sidecars/applications and verify traffic in both directions. A peer's files
370
+ are never changed implicitly. Old published CA anchors remain until deliberately
371
+ retired. Leaf-only renewal needs a sidecar restart, without changing peer trust.
372
+
203
373
  ### Two ways to get your agent's certificates
204
374
 
205
375
  Find your situation here and use the flags it lists. Nothing is inferred:
@@ -227,13 +397,13 @@ The laptop case. The CLI creates a certificate authority on this machine and sig
227
397
 
228
398
  #### I bring my own CA
229
399
 
230
- The production case. Your own issuer has already signed the agent's certificates, and your CA private key never reaches this machine.
400
+ Your own issuer has signed the agent's certificates, and your CA private key never reaches this machine. Certificate source alone does not qualify a production deployment.
231
401
 
232
402
  **Flags.** All seven together: `--workload-cert-file`, `--terminal-cert-file` and `--tls-cert-file`, each with its key file (`--workload-key-file`, `--terminal-key-file`, `--tls-key-file`), plus `--ca-cert-file`. Never `--ca-key-file`: the CLI does not want your CA key.
233
403
 
234
404
  **Keys and signatures.** Your CA's key must be Ed25519 or EC P-256, and it must have signed each certificate with Ed25519 or ECDSA-with-SHA-256. The two identity keys may be Ed25519 or EC P-256; the HTTPS key must be EC P-256. RSA is not supported: the sidecar cannot verify against it.
235
405
 
236
- **The CLI** checks each certificate against its key, its issuer and its validity window; registers the workload and writes the settings files and the pairing secret; publishes your CA certificate as a trust anchor named `<agent>-ca`.
406
+ **The CLI** checks each certificate against its key, its issuer and its validity window, and HTTPS certificates against every configured connection name; registers the workload and writes the settings files and the pairing secret; publishes your CA certificate as a trust anchor named `<agent>-ca`.
237
407
 
238
408
  **The CLI does not** create a certificate authority; issue any certificate; ask for, read or store your CA private key.
239
409
 
@@ -288,8 +458,13 @@ profile (~/.aac/config) ── bound to ──> tenant
288
458
  ### What each file is for, and what to back up
289
459
 
290
460
  The table lists every file the CLI creates, what it is for, how long it
291
- lives and whether to back it up. `<agent>` is the agent name
292
- (default `starter`) and `<tenant-id>` the tenant id AAC allocated.
461
+ lives and whether to back it up. `<agent>` is your explicitly selected agent
462
+ name and `<tenant-id>` the tenant id AAC allocated.
463
+
464
+ For what each of these proves, who else ever gets a copy, what never leaves you
465
+ and how the pieces fit together — including when your own certificate authority
466
+ signs instead of this tool — see
467
+ [Keys and certificates](https://cascadeauth.github.io/aac-sidecar-go/keys-and-certificates.html).
293
468
 
294
469
  <!-- inventory-table:start -->
295
470
  | No. | Material | Where | Used for | Lifetime | Back up? |
@@ -300,9 +475,9 @@ lives and whether to back it up. `<agent>` is the agent name
300
475
  | 4 | root_signing_key | `~/.aac/agents/<agent>/sidecar/root.pem`, `~/.aac/agents/<agent>/sidecar/root.pub.pem`, `~/.aac/tenants/<tenant-id>/root-keys/<agent>-root-v1.pub.pem` | the sidecar mints authority chains; the public half is published under the key id | until you retire its key id (root key ids are fixed per agent name) | No. never restore the private key: a replacement agent gets a new name and therefore a new key id, published alongside the old one until the old one is retired; its public copies are recreated from it |
301
476
  | 5 | development_ca | `~/.aac/agents/<agent>/keep/ca.key`, `~/.aac/agents/<agent>/sidecar/ca.crt`, `~/.aac/agents/<agent>/agent/ca.crt`, `~/.aac/tenants/<tenant-id>/spiffe-bundle/<agent>-dev-ca.ca.pem` | signs the workload, terminal and TLS certificates; peers trust it via the published bundle | 7 days; `aac agent renew --ca` | No. development only; reissue; a lost copy of the certificate is copied back from `sidecar/ca.crt` |
302
477
  | 6 | workload_svid | `~/.aac/agents/<agent>/sidecar/workload.key`, `~/.aac/agents/<agent>/sidecar/workload.crt` | the sidecar's SPIFFE identity: proves on every live request that this workload holds the key behind its certificate | 1 day; `aac agent renew` | No. reissue |
303
- | 7 | terminal_attestation | `~/.aac/agents/<agent>/sidecar/terminal.key`, `~/.aac/agents/<agent>/sidecar/terminal.crt` | signs the receipt (terminal attestation) the sidecar issues when this workload completes a delegated request; auditors verify it offline against your published CA; kept separate from the workload key so neither can forge the other's role | 1 day; `aac agent renew` | No. reissue |
304
- | 8 | localhost_tls | `~/.aac/agents/<agent>/sidecar/server.key`, `~/.aac/agents/<agent>/sidecar/server.crt` | the sidecar's HTTPS listener | 1 day; `aac agent renew` | No. reissue |
305
- | 9 | outbound_ca_bundle | `~/.aac/agents/<agent>/sidecar/outbound-ca.pem` | the sidecar verifies TLS to AAC and to itself | rebuilt by renew; `aac agent renew` | No. derived |
478
+ | 7 | terminal_attestation | `~/.aac/agents/<agent>/sidecar/terminal.key`, `~/.aac/agents/<agent>/sidecar/terminal.crt` | signs the receipt (terminal attestation) the sidecar issues when this workload completes a delegated request; auditors verify it offline against your published CA; setup gives it its own key so the two signing jobs stay separate, but a receipt is verified against your published CA and the expected agent identity, which the workload certificate also satisfies — treat both keys as one blast radius | 1 day; `aac agent renew` | No. reissue |
479
+ | 8 | https_tls | `~/.aac/agents/<agent>/sidecar/server.key`, `~/.aac/agents/<agent>/sidecar/server.crt` | the sidecar's HTTPS listener | 1 day; `aac agent renew` | No. reissue |
480
+ | 9 | outbound_ca_bundle | `~/.aac/agents/<agent>/sidecar/outbound-ca.pem` | the sidecar verifies TLS to AAC and configured peers | rebuilt by renew; `aac agent renew` | No. derived |
306
481
  | 10 | pairing_secret | `~/.aac/agents/<agent>/agent/pairing.secret` | the sidecar and its agent authenticate each other (same bytes in both) | until regenerated | No. regenerable; both processes must read the same file |
307
482
  | 11 | agent_record | `~/.aac/agents/<agent>/record.json` | the agent's identities and progress; every `aac agent` verb reads it first | for the life of the agent | **Recommended.** cannot be recreated by any command; without it start a new agent under a new name (see the new-computer setup procedure) |
308
483
  | 12 | published_public_inputs | `~/.aac/tenants/<tenant-id>/root-keys`, `~/.aac/tenants/<tenant-id>/spiffe-bundle` | the publisher's input directories: every root public key and CA certificate this tenant has published, across all agents | for the life of the tenant | **Recommended.** back up with the tenant directory: a replacement agent must publish its new root key alongside a still-ACTIVE previous one (the control plane refuses a root-key set that drops every ACTIVE key at once) |
@@ -315,11 +490,11 @@ the machine is healthy. Everything else is regenerated.
315
490
  ### Inspect and maintain an agent
316
491
 
317
492
  ```bash
318
- aac agent status --agent starter --output table # what exists, expiry, permissions, next command
319
- aac agent status --agent starter --remote # also: is the public trust material visible?
320
- aac agent renew --agent starter # replace the short-lived certificates; old ones archived
493
+ aac agent status --agent orders --output table # what exists, expiry, permissions, next command
494
+ aac agent status --agent orders --remote # also: is the public trust material visible?
495
+ aac agent renew --agent orders # replace the short-lived certificates; old ones archived
321
496
  aac agent list # every agent on this machine, with its case
322
- aac init --profile stage --agent starter --layout container # write the settings again, container paths
497
+ aac init --profile stage --agent orders --layout container # write the settings again, container paths
323
498
  ```
324
499
 
325
500
  `status` works offline by default and exits with code 3 when material is
@@ -363,7 +538,7 @@ ahead for the development CA.
363
538
 
364
539
  | Material | Lasts | When it runs out | What to do |
365
540
  |---|---|---|---|
366
- | Workload, terminal-attestation and localhost TLS certificates | 1 day | the sidecar can no longer prove its identity, sign receipts or serve HTTPS | `aac agent renew --agent <name>`, then restart the sidecar so it loads them |
541
+ | Workload, terminal-attestation and HTTPS certificates | 1 day | the sidecar can no longer prove its identity, sign receipts or serve HTTPS | `aac agent renew --agent <name>`, then restart the sidecar so it loads them |
367
542
  | Development CA | 7 days | certificates it signed stop being trusted, and no new ones can be issued | `renew` also replaces the CA when it is expired or within a day of expiry, or when `--ca` is given, and then reissues every certificate under it: restart the publisher so the new CA is published, restart the sidecar and anything else that trusted the old CA, and confirm with `aac agent status --agent <name> --remote` |
368
543
  | Tenant-admin session | hours | administration commands ask you to sign in again | `aac sso login` |
369
544
  | Tenant API key, tenant-admin signing key, root signing key | do not expire | — | replaced only on purpose: see "Keys" and "Setting up aac-cli on a new computer" |
@@ -376,10 +551,9 @@ a week that renewal also replaces the development CA (`renew` then reports
376
551
  agent, and anything else that trusted the old CA. Renewing is safe to
377
552
  repeat, but it is not a no-op: every run issues fresh keys and moves the old
378
553
  files to the agent's `archive/` directory, so whatever reads them must
379
- reload. With the
380
- [AAC Compose starter](https://github.com/CascadeAuth/aac-compose-starter),
381
- `./starter up` recreates the containers so they load the new files; it
382
- does not renew anything itself.
554
+ reload. Recreate or restart the affected processes with your deployment's
555
+ normal commands after publishing and explicitly refreshing each peer's public
556
+ trust. Restarting a process does not renew its certificates.
383
557
 
384
558
  All of this is development material. In production, certificates come from
385
559
  your own issuer and follow its renewal process.
@@ -454,12 +628,13 @@ profile; `aac profile show` prints it, and the example below uses
454
628
  directory the publisher runs from. Then run step 3 with
455
629
  `--tenant-admin-key-file tenant-admin.pem` added.
456
630
 
457
- 3. Run the guided setup with a **new agent name**. A developer tenant
631
+ 3. Prepare `laptop-2.yaml` with the new `agent_name` and the original
632
+ workload path, deployment and trust choices. Run setup with that **new agent name**. A developer tenant
458
633
  passes its sign-in choice, so an expired session is renewed without a
459
634
  prompt:
460
635
 
461
636
  ```bash
462
- aac init --profile stage --agent laptop-2 --idp github \
637
+ aac init --profile stage --agent laptop-2 --agent-config laptop-2.yaml --idp github \
463
638
  --trust-url https://trust.stage.cascadeauth.dev
464
639
  ```
465
640
 
@@ -469,7 +644,7 @@ profile; `aac profile show` prints it, and the example below uses
469
644
  the `aac sso login --idp-url …` command from step 1 first:
470
645
 
471
646
  ```bash
472
- aac init --profile stage --agent laptop-2 \
647
+ aac init --profile stage --agent laptop-2 --agent-config laptop-2.yaml \
473
648
  --trust-url https://trust.stage.cascadeauth.dev
474
649
  ```
475
650
 
@@ -731,10 +906,19 @@ aac tenant reissue-api-key --profile prod
731
906
 
732
907
  ### Domains and workloads
733
908
 
734
- Every tenant gets a hosted trust domain from AAC; registration saves it in
735
- the profile, and `aac tenant assign-hosted-domain` assigns one to a tenant
736
- that has none yet. To use your own DNS domain as a trust domain instead,
737
- prove control of it with a DNS TXT record, then bind it:
909
+ Every tenant gets an AAC-assigned trust domain: the tenant id plus a suffix
910
+ the control plane selects for its environment,
911
+ `<tenant_id>.tenants.stage.cascadeauth.dev` on stage and
912
+ `<tenant_id>.tenants.cascadeauth.com` on production. No DNS record or proof
913
+ of ownership is needed; the first call allocates the name permanently and
914
+ every later call returns the same one, so use the name the command returns
915
+ rather than building it yourself. Registration saves it in the profile as
916
+ `hosted_trust_domain`. Signing in with `aac sso login` does not write it:
917
+ `aac tenant assign-hosted-domain` requests the same allocation and saves it
918
+ into the profile bound to that tenant, as `aac init` does during setup. To
919
+ use a custom domain you own as a trust domain instead, prove control of it
920
+ with a DNS TXT record, then bind it; a domain you own is recorded on the
921
+ server and never written to the profile:
738
922
 
739
923
  ```bash
740
924
  aac tenant issue-domain-challenge --profile prod --domain example.com