@astram/guide 0.2.29 → 0.2.30

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.
package/CAPABILITIES.md CHANGED
@@ -254,7 +254,8 @@ imports: [
254
254
  `company` = `{ name, departments?, branches?, roles?: [{ name, permissions }], users?:
255
255
  [{ username, email, company?, postings?: [{ role, department?, branch? }] }], agent?: { mode },
256
256
  children? }`. `agent.mode` (`off` | `synthetic`, identity 0.26) sets that company's AI assistant
257
- mode (below); no `agent` key leaves it unchanged.
257
+ mode (below); no `agent` key leaves it unchanged. A file can never set `live`, and a run refuses
258
+ (`agent_mode_live_locked`) to change a company whose admins approved client data.
258
259
  Unknown fields, unknown permission keys (allowed: catalog keys plus `<feature>:*` and
259
260
  `<feature>:<type>:*`), duplicate usernames or emails and references to undeclared roles,
260
261
  departments or branches are refused before any write. No password, uuid or secret in the file.
@@ -921,7 +922,8 @@ grant a tenant-wide `stored_file` rule for this.
921
922
  server executes. The runtime never calls your app; each capability call it asks for runs inside the
922
923
  user's own streaming request, as that user, through the record pipe and `decide()`, recorded in
923
924
  `agent_action` before it runs. M1: **`read` and `compute` capabilities only**; no workers, no
924
- writes or proposals (M3), no chat UI in the template, synthetic data only (Rule 8).
925
+ writes or proposals (M3), no chat UI in the template, synthetic data by default (Rule 8; real
926
+ client data is a separate gated path, see "Client data to a model provider" below).
925
927
  - **Capabilities.** `defineCapability({ id, version, title, description, effect: 'read' |
926
928
  'compute', dataClass: 'internal' | 'confidential' | 'restricted', requires: [keys], input,
927
929
  output, limits?, handler, toEvidence?, partial? })`, or `inject` + `factory` for app services.
@@ -985,6 +987,8 @@ grant a tenant-wide `stored_file` rule for this.
985
987
  - Files enter a conversation as `attachments` (0–8 `stored_file` uuids your own `FileIntake` route returned)
986
988
  on `POST /agent/tasks` and on `continue` with a message. The runtime only ever gets task handles; any file
987
989
  the user cannot open answers one `404 attachment_unavailable`; a bad list `400 invalid_request`.
990
+ Attaching reads no file content (metadata only); a user may start or continue with attachments at most
991
+ 30 times a minute, then `429 attach_rate_limited` (retryable).
988
992
  - Every byte is parsed by the isolated analyser `@astram/file-analyser` (Python): never formulas, macros,
989
993
  links or embedded objects. Run it as the sidecar container (`docker-compose.analyser.yml` in the
990
994
  scaffold: no network, read-only, non-root) or as the hardened systemd unit in the package's `deploy/`.
@@ -1059,6 +1063,76 @@ grant a tenant-wide `stored_file` rule for this.
1059
1063
  opts out and adds a caution to the kind's `review` / `apply` permission text. Terminal proposals
1060
1064
  are deleted after `PROPOSAL_RETENTION_DAYS` (365, 30–3650); their audit rows stay.
1061
1065
  - Not yet: a review page in the scaffolded template.
1066
+ - **Client-data approval routes (model-provider-client-data phase P2; guard, identity).** A tenant
1067
+ admin approves sending this company's real data to ONE deployment-approved model provider profile.
1068
+ The routes, the stored approvals and the audit trail are described here; how a run uses an approval
1069
+ is in "Client data to a model provider" below. All routes are gated
1070
+ on the new key `identity:agent:client_data_approve`, which is **assigned to no role by default**;
1071
+ note that a role holding `identity:*` or `identity:agent:*` covers it, like `restricted_data`.
1072
+ - `GET /identity/agent/client-data`: the deployment approvals (profile, provider, region, retention,
1073
+ data classes, file content, contract reference, approved by / on; no secrets), whether two-person
1074
+ approval is on, and this company's approvals with history, newest first (≤ 200; people shown by
1075
+ name, never by id).
1076
+ - `POST /identity/agent/client-data/approvals` `{ profile, dataClasses, fileContent, reason, code }`:
1077
+ request an approval. `code` is the admin's own current authenticator code (step-up). With
1078
+ two-person approval (the default) the request is `pending`; without it the approval is `active`
1079
+ at once. `internal` is always included in the classes; the classes and the file flag cannot go
1080
+ beyond the deployment approval.
1081
+ - `POST …/approvals/:uuid/confirm` `{ code }`: a **different** administrator confirms a pending
1082
+ request (step-up again); the deployment approval must still match.
1083
+ - `POST …/approvals/:uuid/revoke` `{ reason }`: revoke a pending or active approval. No step-up
1084
+ (revoking must be fast). The revocation is recorded in Redis first and then in the database; if
1085
+ Redis cannot take it, nothing changes (`503 revoke_unavailable`, retry).
1086
+ - Fixed error codes (`{ statusCode, code, message }`): `profile_not_client_data`,
1087
+ `classes_exceed_deployment`, `file_content_not_allowed`, `invalid_request` (400);
1088
+ `step_up_required`, `confirmer_is_requester`, `forbidden` (403); `approval_not_found` (404, also
1089
+ another company's approval); `approval_pending_exists`, `approval_active_exists`,
1090
+ `approval_not_pending`, `approval_not_revocable`, `approval_state_changed`, `deployment_changed`
1091
+ (409); `too_many_requests` (429); `revoke_unavailable`, `authentication_unavailable`,
1092
+ `unavailable` (503).
1093
+ - An approval writes the company's mode `live`; revoking the last active one writes `off` (never
1094
+ `synthetic`). Org bootstrap still sets `off` / `synthetic` only, and **refuses to change a `live`
1095
+ company** (`agent_mode_live_locked`; revoke in the application first). The refusal comes with
1096
+ `--apply`; a dry run shows the company as `live → <file mode>` and writes nothing. A company that
1097
+ turns `live` after the plan was made is refused again under the row lock, so earlier steps of that
1098
+ run may already have been applied.
1099
+ - Every request, approval and revocation is an `admin_action` audit row
1100
+ (`agent.client_data.requested` / `.approved` / `.revoked`) with the profile, provider, contract
1101
+ reference, classes, file flag and reason; never data. Rows are never deleted.
1102
+ - `@astram/agent` binds `SHIELD_AGENT_CLIENT_DATA_PROFILES` to the booted `client_data` profiles. A
1103
+ profile that did not boot is not approvable: a request answers `400 profile_not_client_data`.
1104
+ - **Client data to a model provider (`@astram/agent`, model-provider-client-data).** Two approvals,
1105
+ neither a code constant. (1) The deployment: a model profile with
1106
+ `providerApproval: { scope: 'client_data', reference, region, retentionDays, dataClasses,
1107
+ approvedBy, approvedOn, fileContent, providerSmoke: { id, date }, runtimeConformance: { id, date,
1108
+ runtimeVersion } }` and the env `AGENT_CLIENT_DATA=1`. (2) The company: its administrators approve
1109
+ the profile through the routes above, which writes mode `live`. Nothing changes unless
1110
+ `AGENT_CLIENT_DATA=1` AND a `client_data` profile are both present. The process must not run with
1111
+ `NODE_TLS_REJECT_UNAUTHORIZED=0` (or `false`): boot refuses it for a `client_data` profile and the
1112
+ runtime client pins certificate verification.
1113
+ - Env, read only with `AGENT_ENABLED=1` (with the agent disabled `AGENT_CLIENT_DATA` is ignored and
1114
+ one fixed boot line says so): `AGENT_CLIENT_DATA` (`0` default | `1`) and
1115
+ `AGENT_EGRESS_POLICY_ACK` (`<verificationId>@<YYYY-MM-DD>`, at most 180 days old).
1116
+ `AgentModule.forRoot({ clientData: { twoPerson } })` defaults to `true`; `false` logs a warning at
1117
+ every boot.
1118
+ - A `client_data` profile boots only when, in this order, `env`, `masking`, `outbound_audit`,
1119
+ `egress_verification`, `runtime_conformance`, `provider_smoke` and `https` hold (boot error
1120
+ `modelProfiles.<name>: client_data_prerequisite (<which>)`; an `http:` runtime URL is refused in
1121
+ every environment, loopback included). With all of them met the profile boots.
1122
+ - A client-data run sends `dataScope: "client_data"` in its signed run request and only to a
1123
+ runtime whose verified `GET /v0/info` lists `client_data` and the `data-scope` feature at an
1124
+ agent-protocol minor at least the app's; otherwise the run ends `data_scope_unsupported` before
1125
+ anything is sent (the runtime must be on agent-protocol 0.5 or later, over `https:`, ideally with
1126
+ its durable state backend). Synthetic runs are unchanged. When the runtime lists `answers.v1`, an
1127
+ answers turn also sends the structured answers (free text masked; the flattened message copy is
1128
+ not). The app sends `history` unchanged: the runtime treats it as an untrusted data block
1129
+ (agent-protocol 0.5, a runtime requirement).
1130
+ - A run on a `live` company needs a booted `client_data` profile with an active approval, else
1131
+ `403 agent_client_data_not_approved`. The approval is read on every call and every send (revoke
1132
+ marker first, never cached); when it ends or narrows the task stops with `client_data_revoked`.
1133
+ A capability's data class must be in the approval's classes. File content goes to the provider
1134
+ only if the approval allows it (decided per run); org bootstrap still refuses a non-empty
1135
+ `agent.fileProviders` outside development/test. Masking is always on.
1062
1136
 
1063
1137
  ## Available, but NOT wired to a data path (do not assume they protect data yet)
1064
1138
  - **Envelope encryption / per-tenant DEKs** (`createEncryptionService`, `LocalKekCrypto`): the
@@ -180,9 +180,11 @@ makes every model call and never calls your app.
180
180
  lists rows returns how many exist, not only the page.
181
181
  - **No uuids to the model.** Return handles (`ctx.handle(uuid, typeKey)`) and declare handle inputs
182
182
  with `"x-astram-handle"`; never put a uuid, id or hex digest in a capability's output.
183
- - **Synthetic data only.** Enable a tenant (`agent: { mode: "synthetic" }` in the org bootstrap
184
- file) only when it holds synthetic data. Never set a model profile's `providerApproval.scope` to
185
- `client_data`; the framework refuses it until real data is approved.
183
+ - **Synthetic data by default.** Enable a tenant (`agent: { mode: "synthetic" }` in the org bootstrap
184
+ file) only when it holds synthetic data. Do not set a model profile's `providerApproval.scope` to
185
+ `client_data` or `AGENT_CLIENT_DATA=1` unless the platform owner has approved real data for that
186
+ provider; the company's administrators then approve it in the application (see
187
+ "Client data to a model provider" in CAPABILITIES.md). Never write a `live` mode yourself.
186
188
 
187
189
  ---
188
190
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astram/guide",
3
- "version": "0.2.29",
3
+ "version": "0.2.30",
4
4
  "license": "MIT",
5
5
  "description": "Astram framework — the AI/dev GUIDE layer (ADR-0025). Ships the framework's hard rules + capabilities manifest as installed, upgrade-refreshed docs. A consumer app's CLAUDE.md references FRAMEWORK_RULES.md from this package; `npm update` replaces it wholesale so new rules arrive cleanly, while the app's own .astram/guide/ layer is never touched. This is the framework-owned FLOOR: an app rule may tighten it, never weaken it.",
6
6
  "type": "commonjs",