@highflame/policy 2.2.27 → 2.2.28

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.
@@ -131,6 +131,74 @@
131
131
  "required": false,
132
132
  "description": "Organization that published the agent (e.g., 'anthropic', 'internal', 'acme-corp')."
133
133
  }
134
+ ],
135
+ "flow_label_keys": [
136
+ {
137
+ "key": "flow_confidentiality",
138
+ "type": "string",
139
+ "required": false,
140
+ "description": "Confidentiality tier of the data this action carries or targets (ADR 0020): 'public', 'internal', 'confidential', 'restricted', or 'unknown'. Shares the ladder with session_max_sensitivity but is a per-value fact, not a session scalar. 'unknown' MUST NOT be treated as 'public' — guard with has and let policy DENY/STEP_UP/DEFER per flow_resolution_status."
141
+ },
142
+ {
143
+ "key": "flow_integrity",
144
+ "type": "string",
145
+ "required": false,
146
+ "description": "Integrity/influence tier of the data this action carries (ADR 0020): 'trusted', 'untrusted', 'mixed', or 'unknown'. Orthogonal to confidentiality: untrusted content may inform a pure analysis but MUST NOT authorize a side-effecting sink. Least-trusted contributor wins on join."
147
+ },
148
+ {
149
+ "key": "flow_data_types",
150
+ "type": "array",
151
+ "required": false,
152
+ "description": "Sensitive data categories present in the value (ADR 0020), e.g. 'pii', 'secrets', 'source_code', 'financial', 'health'. Union of all contributing inputs. Set<String>."
153
+ },
154
+ {
155
+ "key": "flow_compartments",
156
+ "type": "array",
157
+ "required": false,
158
+ "description": "Compartments the value belongs to (ADR 0020), e.g. 'tenant:acme', 'customer:123', 'project:x'. Union of all contributing inputs — cross-compartment composition is expressible by cardinality. Set<String>."
159
+ },
160
+ {
161
+ "key": "flow_resolution_status",
162
+ "type": "string",
163
+ "required": false,
164
+ "description": "How the flow label was resolved (ADR 0020): 'known', 'inferred', 'unknown', or 'conflicted'. Policy authors choose the posture for 'unknown' per sink (DENY external, STEP_UP, DEFER while a classifier runs, or allow-and-record). Never silently resolves to public."
165
+ },
166
+ {
167
+ "key": "flow_origins",
168
+ "type": "array",
169
+ "required": false,
170
+ "description": "Origin kinds that produced or influenced the value (ADR 0020): 'mcp_tool_result', 'model', 'file', 'database', 'user'. Provenance fact for lineage-aware policy. Set<String>."
171
+ },
172
+ {
173
+ "key": "flow_sink",
174
+ "type": "string",
175
+ "required": false,
176
+ "description": "Logical destination this action releases the value to (ADR 0020), e.g. 'external_model', 'local_model', 'external_mcp', 'trusted_mcp', 'user_secure_output', 'public_network', 'file'. The 'where' half of a flow decision — pair with flow_confidentiality/flow_integrity."
177
+ },
178
+ {
179
+ "key": "flow_sink_is_external",
180
+ "type": "boolean",
181
+ "required": false,
182
+ "description": "Whether the destination is outside the tenant trust boundary (ADR 0020). Lets a single policy express 'confidential data MUST NOT leave to any external sink' without enumerating sink ids."
183
+ },
184
+ {
185
+ "key": "flow_sink_effects",
186
+ "type": "array",
187
+ "required": false,
188
+ "description": "Side effects the destination can exercise (ADR 0020), e.g. 'network.send', 'financial.transfer', 'filesystem.write'. Enables 'untrusted content MUST NOT reach a financial.transfer sink'. Set<String>."
189
+ },
190
+ {
191
+ "key": "principal_clearances",
192
+ "type": "array",
193
+ "required": false,
194
+ "description": "Clearances AuthN/ZeroID mints for the principal (ADR 0020 D8), e.g. 'restricted', 'pii'. Coarse scopes gate the capability; clearances gate which protected data that capability may touch. Set<String>."
195
+ },
196
+ {
197
+ "key": "principal_compartments",
198
+ "type": "array",
199
+ "required": false,
200
+ "description": "Compartments the principal is admitted to (ADR 0020 D8), e.g. 'tenant:acme', 'customer:123'. A flow into a compartment the principal lacks is deniable independent of confidentiality tier. Set<String>."
201
+ }
134
202
  ]
135
203
  },
136
204
  "actions": [
@@ -676,8 +744,35 @@
676
744
  "required": false,
677
745
  "description": "Whether the token budget has been exceeded"
678
746
  },
747
+ {
748
+ "key": "rpm_remaining_pct",
749
+ "type": "number",
750
+ "required": false,
751
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
752
+ "range": "0-100"
753
+ },
754
+ {
755
+ "key": "rpm_exceeded",
756
+ "type": "boolean",
757
+ "required": false,
758
+ "description": "Whether the RPM limit has been exceeded"
759
+ },
760
+ {
761
+ "key": "tpm_remaining_pct",
762
+ "type": "number",
763
+ "required": false,
764
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
765
+ "range": "0-100"
766
+ },
767
+ {
768
+ "key": "tpm_exceeded",
769
+ "type": "boolean",
770
+ "required": false,
771
+ "description": "Whether the TPM limit has been exceeded"
772
+ },
679
773
  { "$ref": "session_keys" },
680
- { "$ref": "agent_identity_keys" }
774
+ { "$ref": "agent_identity_keys" },
775
+ { "$ref": "flow_label_keys" }
681
776
  ]
682
777
  },
683
778
  {
@@ -1145,6 +1240,32 @@
1145
1240
  "required": false,
1146
1241
  "description": "Whether the token budget has been exceeded"
1147
1242
  },
1243
+ {
1244
+ "key": "rpm_remaining_pct",
1245
+ "type": "number",
1246
+ "required": false,
1247
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1248
+ "range": "0-100"
1249
+ },
1250
+ {
1251
+ "key": "rpm_exceeded",
1252
+ "type": "boolean",
1253
+ "required": false,
1254
+ "description": "Whether the RPM limit has been exceeded"
1255
+ },
1256
+ {
1257
+ "key": "tpm_remaining_pct",
1258
+ "type": "number",
1259
+ "required": false,
1260
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1261
+ "range": "0-100"
1262
+ },
1263
+ {
1264
+ "key": "tpm_exceeded",
1265
+ "type": "boolean",
1266
+ "required": false,
1267
+ "description": "Whether the TPM limit has been exceeded"
1268
+ },
1148
1269
  {
1149
1270
  "key": "highest_severity",
1150
1271
  "type": "string",
@@ -1164,7 +1285,8 @@
1164
1285
  "description": "Array of specific threat names detected"
1165
1286
  },
1166
1287
  { "$ref": "session_keys" },
1167
- { "$ref": "agent_identity_keys" }
1288
+ { "$ref": "agent_identity_keys" },
1289
+ { "$ref": "flow_label_keys" }
1168
1290
  ]
1169
1291
  },
1170
1292
  {
@@ -1322,8 +1444,35 @@
1322
1444
  "required": false,
1323
1445
  "description": "Whether the token budget has been exceeded"
1324
1446
  },
1447
+ {
1448
+ "key": "rpm_remaining_pct",
1449
+ "type": "number",
1450
+ "required": false,
1451
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1452
+ "range": "0-100"
1453
+ },
1454
+ {
1455
+ "key": "rpm_exceeded",
1456
+ "type": "boolean",
1457
+ "required": false,
1458
+ "description": "Whether the RPM limit has been exceeded"
1459
+ },
1460
+ {
1461
+ "key": "tpm_remaining_pct",
1462
+ "type": "number",
1463
+ "required": false,
1464
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1465
+ "range": "0-100"
1466
+ },
1467
+ {
1468
+ "key": "tpm_exceeded",
1469
+ "type": "boolean",
1470
+ "required": false,
1471
+ "description": "Whether the TPM limit has been exceeded"
1472
+ },
1325
1473
  { "$ref": "session_keys" },
1326
- { "$ref": "agent_identity_keys" }
1474
+ { "$ref": "agent_identity_keys" },
1475
+ { "$ref": "flow_label_keys" }
1327
1476
  ]
1328
1477
  },
1329
1478
  {
@@ -1494,8 +1643,35 @@
1494
1643
  "required": false,
1495
1644
  "description": "Whether the token budget has been exceeded"
1496
1645
  },
1646
+ {
1647
+ "key": "rpm_remaining_pct",
1648
+ "type": "number",
1649
+ "required": false,
1650
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1651
+ "range": "0-100"
1652
+ },
1653
+ {
1654
+ "key": "rpm_exceeded",
1655
+ "type": "boolean",
1656
+ "required": false,
1657
+ "description": "Whether the RPM limit has been exceeded"
1658
+ },
1659
+ {
1660
+ "key": "tpm_remaining_pct",
1661
+ "type": "number",
1662
+ "required": false,
1663
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1664
+ "range": "0-100"
1665
+ },
1666
+ {
1667
+ "key": "tpm_exceeded",
1668
+ "type": "boolean",
1669
+ "required": false,
1670
+ "description": "Whether the TPM limit has been exceeded"
1671
+ },
1497
1672
  { "$ref": "session_keys" },
1498
- { "$ref": "agent_identity_keys" }
1673
+ { "$ref": "agent_identity_keys" },
1674
+ { "$ref": "flow_label_keys" }
1499
1675
  ]
1500
1676
  },
1501
1677
  {
@@ -1668,8 +1844,119 @@
1668
1844
  "required": false,
1669
1845
  "description": "Whether the token budget has been exceeded"
1670
1846
  },
1847
+ {
1848
+ "key": "rpm_remaining_pct",
1849
+ "type": "number",
1850
+ "required": false,
1851
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1852
+ "range": "0-100"
1853
+ },
1854
+ {
1855
+ "key": "rpm_exceeded",
1856
+ "type": "boolean",
1857
+ "required": false,
1858
+ "description": "Whether the RPM limit has been exceeded"
1859
+ },
1860
+ {
1861
+ "key": "tpm_remaining_pct",
1862
+ "type": "number",
1863
+ "required": false,
1864
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1865
+ "range": "0-100"
1866
+ },
1867
+ {
1868
+ "key": "tpm_exceeded",
1869
+ "type": "boolean",
1870
+ "required": false,
1871
+ "description": "Whether the TPM limit has been exceeded"
1872
+ },
1671
1873
  { "$ref": "session_keys" },
1672
- { "$ref": "agent_identity_keys" }
1874
+ { "$ref": "agent_identity_keys" },
1875
+ { "$ref": "flow_label_keys" }
1876
+ ]
1877
+ },
1878
+ {
1879
+ "name": "provision_sandbox",
1880
+ "description": "Provision a sandbox for the acting identity (Forge OS-layer envelope). Mandatory authorization gate for sandbox creation (ADR 0019). Every capability attribute is optional and describes the requested envelope; rules MUST guard each with `has` before access (an absent-attribute access errors, silently voiding a forbid — fail-open).",
1881
+ "context_attributes": [
1882
+ {
1883
+ "key": "role",
1884
+ "type": "string",
1885
+ "required": false,
1886
+ "description": "Caller's RBAC role projected from the principal's token"
1887
+ },
1888
+ {
1889
+ "key": "privilege_scope",
1890
+ "type": "array",
1891
+ "required": false,
1892
+ "description": "Privilege-scope strings granted to the caller"
1893
+ },
1894
+ {
1895
+ "key": "identity_type",
1896
+ "type": "string",
1897
+ "required": false,
1898
+ "description": "Principal identity class: 'human', 'agent', 'service', or 'mcp_server'"
1899
+ },
1900
+ {
1901
+ "key": "principal",
1902
+ "type": "string",
1903
+ "required": false,
1904
+ "description": "Stable principal identifier (ZeroID / WIMSE URI or user id)"
1905
+ },
1906
+ {
1907
+ "key": "agent_trust_level",
1908
+ "type": "string",
1909
+ "required": false,
1910
+ "description": "Agent trust tier: 'untrusted' | 'low' | 'verified' | 'trusted'"
1911
+ },
1912
+ {
1913
+ "key": "request_id",
1914
+ "type": "string",
1915
+ "required": true,
1916
+ "description": "Unique identifier for this request"
1917
+ },
1918
+ {
1919
+ "key": "timestamp",
1920
+ "type": "number",
1921
+ "required": true,
1922
+ "description": "Unix timestamp in milliseconds"
1923
+ },
1924
+ {
1925
+ "key": "isolation_tier",
1926
+ "type": "string",
1927
+ "required": true,
1928
+ "description": "Requested OS-isolation tier as the lowercased Forge IsolationTier name (ADR 0016 D1). Ordinal, weakest→strongest: 'none' < 'os' < 'kernel' (gVisor) < 'hardware' (micro-VM + TEE). Templates assert a floor via set membership; Forge owns the ordering."
1929
+ },
1930
+ {
1931
+ "key": "writable_paths",
1932
+ "type": "array",
1933
+ "required": false,
1934
+ "description": "Writable path prefixes the sandbox is requesting, e.g. ['/scratch']"
1935
+ },
1936
+ {
1937
+ "key": "network_egress",
1938
+ "type": "boolean",
1939
+ "required": false,
1940
+ "description": "Whether any outbound network egress is requested"
1941
+ },
1942
+ {
1943
+ "key": "egress_hosts",
1944
+ "type": "array",
1945
+ "required": false,
1946
+ "description": "Host allowlist for egress, e.g. ['pypi.org', 'files.pythonhosted.org']"
1947
+ },
1948
+ {
1949
+ "key": "exec_allowlist",
1950
+ "type": "array",
1951
+ "required": false,
1952
+ "description": "Executables the sandbox may run, e.g. ['python', 'python3']"
1953
+ },
1954
+ {
1955
+ "key": "mechanism_capabilities",
1956
+ "type": "array",
1957
+ "required": false,
1958
+ "description": "Curated mechanism toggles (ADR 0017 D1.3) — authorization facts only, never raw syscalls. Allowed members: 'sys:ptrace', 'sys:bpf', 'sys:raw_socket', 'dev:gpu', 'virt:nested'."
1959
+ }
1673
1960
  ]
1674
1961
  }
1675
1962
  ]
@@ -95,6 +95,19 @@ namespace AgentOps {
95
95
  context: ConnectServerContext
96
96
  };
97
97
 
98
+ /// Provision a sandbox for the acting identity (Forge OS-layer envelope).
99
+ /// The MANDATORY authorization gate for sandbox creation (ADR 0019 D1):
100
+ /// Forge evaluates this action's AgentOps bundle at create-time; no decision
101
+ /// means no sandbox. Context carries the requested capability envelope
102
+ /// (writable paths, egress, exec allowlist, curated mechanism toggles,
103
+ /// isolation tier). Raw syscalls are NEVER expressed here — the enforcement
104
+ /// generators own the mechanism→syscall translation (ADR 0017 D1).
105
+ action "provision_sandbox" appliesTo {
106
+ principal: [User, Agent],
107
+ resource: [Agent, Session],
108
+ context: ProvisionSandboxContext
109
+ };
110
+
98
111
  // =========================================================================
99
112
  // Context Types (Action-Specific)
100
113
  // =========================================================================
@@ -233,6 +246,21 @@ namespace AgentOps {
233
246
  "session_original_request"?: String,
234
247
  "session_max_sensitivity"?: String,
235
248
 
249
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
250
+ // All optional: guard every access with `has` — an absent-attribute read is
251
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
252
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
253
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
254
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
255
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
256
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
257
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
258
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
259
+ "flow_sink_is_external"?: Boolean,
260
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
261
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
262
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
263
+
236
264
  // Usage Budget — multi-window token & cost enforcement (optional)
237
265
  "budget_remaining_pct"?: Long,
238
266
  "budget_exceeded"?: Boolean,
@@ -247,6 +275,12 @@ namespace AgentOps {
247
275
  "budget_exceeded_daily"?: Boolean,
248
276
  "budget_exceeded_monthly"?: Boolean,
249
277
 
278
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
279
+ "rpm_remaining_pct"?: Long,
280
+ "rpm_exceeded"?: Boolean,
281
+ "tpm_remaining_pct"?: Long,
282
+ "tpm_exceeded"?: Boolean,
283
+
250
284
  // Agent Identity — authenticated agent principal metadata (optional)
251
285
  "agent_id"?: String,
252
286
  "agent_type"?: String, // "orchestrator" | "autonomous" | "tool_agent" | "human_proxy"
@@ -391,6 +425,21 @@ namespace AgentOps {
391
425
  "session_original_request"?: String,
392
426
  "session_max_sensitivity"?: String,
393
427
 
428
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
429
+ // All optional: guard every access with `has` — an absent-attribute read is
430
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
431
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
432
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
433
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
434
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
435
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
436
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
437
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
438
+ "flow_sink_is_external"?: Boolean,
439
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
440
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
441
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
442
+
394
443
  // Usage Budget (optional)
395
444
  "budget_remaining_pct"?: Long,
396
445
  "budget_exceeded"?: Boolean,
@@ -405,6 +454,12 @@ namespace AgentOps {
405
454
  "budget_exceeded_daily"?: Boolean,
406
455
  "budget_exceeded_monthly"?: Boolean,
407
456
 
457
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
458
+ "rpm_remaining_pct"?: Long,
459
+ "rpm_exceeded"?: Boolean,
460
+ "tpm_remaining_pct"?: Long,
461
+ "tpm_exceeded"?: Boolean,
462
+
408
463
  // Aggregated threat summary (optional)
409
464
  "highest_severity"?: String,
410
465
  "threat_count"?: Long,
@@ -477,6 +532,21 @@ namespace AgentOps {
477
532
  "session_original_request"?: String,
478
533
  "session_max_sensitivity"?: String,
479
534
 
535
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
536
+ // All optional: guard every access with `has` — an absent-attribute read is
537
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
538
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
539
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
540
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
541
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
542
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
543
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
544
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
545
+ "flow_sink_is_external"?: Boolean,
546
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
547
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
548
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
549
+
480
550
  // Usage Budget (optional)
481
551
  "budget_remaining_pct"?: Long,
482
552
  "budget_exceeded"?: Boolean,
@@ -491,6 +561,12 @@ namespace AgentOps {
491
561
  "budget_exceeded_daily"?: Boolean,
492
562
  "budget_exceeded_monthly"?: Boolean,
493
563
 
564
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
565
+ "rpm_remaining_pct"?: Long,
566
+ "rpm_exceeded"?: Boolean,
567
+ "tpm_remaining_pct"?: Long,
568
+ "tpm_exceeded"?: Boolean,
569
+
494
570
  // Agent Identity (optional)
495
571
  "agent_id"?: String,
496
572
  "agent_type"?: String,
@@ -559,6 +635,21 @@ namespace AgentOps {
559
635
  "session_original_request"?: String,
560
636
  "session_max_sensitivity"?: String,
561
637
 
638
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
639
+ // All optional: guard every access with `has` — an absent-attribute read is
640
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
641
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
642
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
643
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
644
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
645
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
646
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
647
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
648
+ "flow_sink_is_external"?: Boolean,
649
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
650
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
651
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
652
+
562
653
  // Usage Budget (optional)
563
654
  "budget_remaining_pct"?: Long,
564
655
  "budget_exceeded"?: Boolean,
@@ -573,6 +664,12 @@ namespace AgentOps {
573
664
  "budget_exceeded_daily"?: Boolean,
574
665
  "budget_exceeded_monthly"?: Boolean,
575
666
 
667
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
668
+ "rpm_remaining_pct"?: Long,
669
+ "rpm_exceeded"?: Boolean,
670
+ "tpm_remaining_pct"?: Long,
671
+ "tpm_exceeded"?: Boolean,
672
+
576
673
  // Agent Identity (optional)
577
674
  "agent_id"?: String,
578
675
  "agent_type"?: String,
@@ -641,6 +738,21 @@ namespace AgentOps {
641
738
  "session_original_request"?: String,
642
739
  "session_max_sensitivity"?: String,
643
740
 
741
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
742
+ // All optional: guard every access with `has` — an absent-attribute read is
743
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
744
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
745
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
746
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
747
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
748
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
749
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
750
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
751
+ "flow_sink_is_external"?: Boolean,
752
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
753
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
754
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
755
+
644
756
  // Usage Budget (optional)
645
757
  "budget_remaining_pct"?: Long,
646
758
  "budget_exceeded"?: Boolean,
@@ -655,6 +767,12 @@ namespace AgentOps {
655
767
  "budget_exceeded_daily"?: Boolean,
656
768
  "budget_exceeded_monthly"?: Boolean,
657
769
 
770
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
771
+ "rpm_remaining_pct"?: Long,
772
+ "rpm_exceeded"?: Boolean,
773
+ "tpm_remaining_pct"?: Long,
774
+ "tpm_exceeded"?: Boolean,
775
+
658
776
  // Agent Identity (optional)
659
777
  "agent_id"?: String,
660
778
  "agent_type"?: String,
@@ -663,4 +781,53 @@ namespace AgentOps {
663
781
  "agent_publisher"?: String,
664
782
 
665
783
  };
784
+
785
+ /// Context for provision_sandbox action (Forge sandbox-create envelope).
786
+ ///
787
+ /// Every capability field below is OPTIONAL and describes the envelope the
788
+ /// sandbox is being asked to provision with — Forge synthesizes it from the
789
+ /// create request attenuated by the token's scope ceiling (ADR 0019 D1),
790
+ /// then asks Cedar whether this identity may provision it. Profile templates
791
+ /// `permit` provision_sandbox only when the requested envelope stays within
792
+ /// the profile ceiling, and `forbid` any escalation beyond it.
793
+ ///
794
+ /// FAIL-OPEN WARNING (ADR 0019 D3): because these attributes are optional,
795
+ /// accessing an absent one is a Cedar *evaluation error*, and an errored
796
+ /// `forbid` is silently skipped — which fails OPEN. Every rule touching a
797
+ /// field here MUST guard it first with `has` (e.g.
798
+ /// `context has mechanism_capabilities && context.mechanism_capabilities.contains("sys:ptrace")`).
799
+ type ProvisionSandboxContext = {
800
+ // Identity (AARM R6 / CAP-IDN-011) — projected from the principal's token; optional.
801
+ "role"?: String,
802
+ "privilege_scope"?: Set<String>,
803
+ "identity_type"?: String, // Principal identity class: "human" | "agent" | "service" | "mcp_server"
804
+ "principal"?: String, // Stable principal identifier (ZeroID / WIMSE URI or user id)
805
+ "agent_trust_level"?: String, // "untrusted" | "low" | "verified" | "trusted"
806
+
807
+ // Core metadata (required)
808
+ "request_id": String,
809
+ "timestamp": Long,
810
+
811
+ // Requested isolation tier (required) — the OS-isolation tier the
812
+ // sandbox will run at, as the lowercased Forge IsolationTier name (ADR
813
+ // 0016 D1). Ordinal, weakest→strongest: "none" (trusted-local) < "os"
814
+ // (bwrap/seatbelt) < "kernel" (gVisor) < "hardware" (micro-VM + TEE).
815
+ // Templates assert a floor via set membership (e.g. a KERNEL floor =
816
+ // {"kernel","hardware"}); Forge owns the ordering.
817
+ "isolation_tier": String,
818
+
819
+ // Requested capability envelope (all optional — has-guard mandatory).
820
+ "writable_paths"?: Set<String>, // Writable path prefixes, e.g. {"/scratch"}
821
+ // Master egress switch. Forge MUST set this true whenever ANY egress is
822
+ // requested (i.e. whenever egress_hosts is non-empty), so a "no network"
823
+ // profile can gate on this single boolean. egress_hosts then narrows the
824
+ // host allowlist for profiles that DO permit egress.
825
+ "network_egress"?: Boolean,
826
+ "egress_hosts"?: Set<String>, // Host allowlist for egress, e.g. {"pypi.org"}
827
+ "exec_allowlist"?: Set<String>, // Executables the sandbox may run, e.g. {"python", "python3"}
828
+ // Curated mechanism toggles (ADR 0017 D1.3) — authorization facts only;
829
+ // NEVER raw syscalls. Allowed members: "sys:ptrace", "sys:bpf",
830
+ // "sys:raw_socket", "dev:gpu", "virt:nested".
831
+ "mechanism_capabilities"?: Set<String>,
832
+ };
666
833
  }