@highflame/policy 2.2.27 → 2.2.29

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,82 @@
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
+ }
202
+ ],
203
+ "surface_keys": [
204
+ {
205
+ "key": "surface",
206
+ "type": "string",
207
+ "required": true,
208
+ "description": "Origin surface of the request (ADR 0012 D14.2) — REQUIRED; projected by Shield from the ingress product, never user-supplied. Values are the product identifiers: 'guardrails', 'overwatch', 'ai_gateway' ('sentry' joins at D17 phase 2). The 'Applies to' narrowing target: test with an ordinary condition (context.surface == 'ai_gateway'); no 'has' guard needed because it is required. A policy with no surface condition applies to every surface, including ones added later."
209
+ }
134
210
  ]
135
211
  },
136
212
  "actions": [
@@ -676,8 +752,36 @@
676
752
  "required": false,
677
753
  "description": "Whether the token budget has been exceeded"
678
754
  },
755
+ {
756
+ "key": "rpm_remaining_pct",
757
+ "type": "number",
758
+ "required": false,
759
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
760
+ "range": "0-100"
761
+ },
762
+ {
763
+ "key": "rpm_exceeded",
764
+ "type": "boolean",
765
+ "required": false,
766
+ "description": "Whether the RPM limit has been exceeded"
767
+ },
768
+ {
769
+ "key": "tpm_remaining_pct",
770
+ "type": "number",
771
+ "required": false,
772
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
773
+ "range": "0-100"
774
+ },
775
+ {
776
+ "key": "tpm_exceeded",
777
+ "type": "boolean",
778
+ "required": false,
779
+ "description": "Whether the TPM limit has been exceeded"
780
+ },
679
781
  { "$ref": "session_keys" },
680
- { "$ref": "agent_identity_keys" }
782
+ { "$ref": "agent_identity_keys" },
783
+ { "$ref": "flow_label_keys" },
784
+ { "$ref": "surface_keys" }
681
785
  ]
682
786
  },
683
787
  {
@@ -1145,6 +1249,32 @@
1145
1249
  "required": false,
1146
1250
  "description": "Whether the token budget has been exceeded"
1147
1251
  },
1252
+ {
1253
+ "key": "rpm_remaining_pct",
1254
+ "type": "number",
1255
+ "required": false,
1256
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1257
+ "range": "0-100"
1258
+ },
1259
+ {
1260
+ "key": "rpm_exceeded",
1261
+ "type": "boolean",
1262
+ "required": false,
1263
+ "description": "Whether the RPM limit has been exceeded"
1264
+ },
1265
+ {
1266
+ "key": "tpm_remaining_pct",
1267
+ "type": "number",
1268
+ "required": false,
1269
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1270
+ "range": "0-100"
1271
+ },
1272
+ {
1273
+ "key": "tpm_exceeded",
1274
+ "type": "boolean",
1275
+ "required": false,
1276
+ "description": "Whether the TPM limit has been exceeded"
1277
+ },
1148
1278
  {
1149
1279
  "key": "highest_severity",
1150
1280
  "type": "string",
@@ -1164,7 +1294,9 @@
1164
1294
  "description": "Array of specific threat names detected"
1165
1295
  },
1166
1296
  { "$ref": "session_keys" },
1167
- { "$ref": "agent_identity_keys" }
1297
+ { "$ref": "agent_identity_keys" },
1298
+ { "$ref": "flow_label_keys" },
1299
+ { "$ref": "surface_keys" }
1168
1300
  ]
1169
1301
  },
1170
1302
  {
@@ -1322,8 +1454,36 @@
1322
1454
  "required": false,
1323
1455
  "description": "Whether the token budget has been exceeded"
1324
1456
  },
1457
+ {
1458
+ "key": "rpm_remaining_pct",
1459
+ "type": "number",
1460
+ "required": false,
1461
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1462
+ "range": "0-100"
1463
+ },
1464
+ {
1465
+ "key": "rpm_exceeded",
1466
+ "type": "boolean",
1467
+ "required": false,
1468
+ "description": "Whether the RPM limit has been exceeded"
1469
+ },
1470
+ {
1471
+ "key": "tpm_remaining_pct",
1472
+ "type": "number",
1473
+ "required": false,
1474
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1475
+ "range": "0-100"
1476
+ },
1477
+ {
1478
+ "key": "tpm_exceeded",
1479
+ "type": "boolean",
1480
+ "required": false,
1481
+ "description": "Whether the TPM limit has been exceeded"
1482
+ },
1325
1483
  { "$ref": "session_keys" },
1326
- { "$ref": "agent_identity_keys" }
1484
+ { "$ref": "agent_identity_keys" },
1485
+ { "$ref": "flow_label_keys" },
1486
+ { "$ref": "surface_keys" }
1327
1487
  ]
1328
1488
  },
1329
1489
  {
@@ -1494,8 +1654,36 @@
1494
1654
  "required": false,
1495
1655
  "description": "Whether the token budget has been exceeded"
1496
1656
  },
1657
+ {
1658
+ "key": "rpm_remaining_pct",
1659
+ "type": "number",
1660
+ "required": false,
1661
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1662
+ "range": "0-100"
1663
+ },
1664
+ {
1665
+ "key": "rpm_exceeded",
1666
+ "type": "boolean",
1667
+ "required": false,
1668
+ "description": "Whether the RPM limit has been exceeded"
1669
+ },
1670
+ {
1671
+ "key": "tpm_remaining_pct",
1672
+ "type": "number",
1673
+ "required": false,
1674
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1675
+ "range": "0-100"
1676
+ },
1677
+ {
1678
+ "key": "tpm_exceeded",
1679
+ "type": "boolean",
1680
+ "required": false,
1681
+ "description": "Whether the TPM limit has been exceeded"
1682
+ },
1497
1683
  { "$ref": "session_keys" },
1498
- { "$ref": "agent_identity_keys" }
1684
+ { "$ref": "agent_identity_keys" },
1685
+ { "$ref": "flow_label_keys" },
1686
+ { "$ref": "surface_keys" }
1499
1687
  ]
1500
1688
  },
1501
1689
  {
@@ -1668,8 +1856,120 @@
1668
1856
  "required": false,
1669
1857
  "description": "Whether the token budget has been exceeded"
1670
1858
  },
1859
+ {
1860
+ "key": "rpm_remaining_pct",
1861
+ "type": "number",
1862
+ "required": false,
1863
+ "description": "Remaining RPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1864
+ "range": "0-100"
1865
+ },
1866
+ {
1867
+ "key": "rpm_exceeded",
1868
+ "type": "boolean",
1869
+ "required": false,
1870
+ "description": "Whether the RPM limit has been exceeded"
1871
+ },
1872
+ {
1873
+ "key": "tpm_remaining_pct",
1874
+ "type": "number",
1875
+ "required": false,
1876
+ "description": "Remaining TPM percentage (0-100). Gateway-metered, Shield-decided (ADR 0014).",
1877
+ "range": "0-100"
1878
+ },
1879
+ {
1880
+ "key": "tpm_exceeded",
1881
+ "type": "boolean",
1882
+ "required": false,
1883
+ "description": "Whether the TPM limit has been exceeded"
1884
+ },
1671
1885
  { "$ref": "session_keys" },
1672
- { "$ref": "agent_identity_keys" }
1886
+ { "$ref": "agent_identity_keys" },
1887
+ { "$ref": "flow_label_keys" },
1888
+ { "$ref": "surface_keys" }
1889
+ ]
1890
+ },
1891
+ {
1892
+ "name": "provision_sandbox",
1893
+ "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).",
1894
+ "context_attributes": [
1895
+ {
1896
+ "key": "role",
1897
+ "type": "string",
1898
+ "required": false,
1899
+ "description": "Caller's RBAC role projected from the principal's token"
1900
+ },
1901
+ {
1902
+ "key": "privilege_scope",
1903
+ "type": "array",
1904
+ "required": false,
1905
+ "description": "Privilege-scope strings granted to the caller"
1906
+ },
1907
+ {
1908
+ "key": "identity_type",
1909
+ "type": "string",
1910
+ "required": false,
1911
+ "description": "Principal identity class: 'human', 'agent', 'service', or 'mcp_server'"
1912
+ },
1913
+ {
1914
+ "key": "principal",
1915
+ "type": "string",
1916
+ "required": false,
1917
+ "description": "Stable principal identifier (ZeroID / WIMSE URI or user id)"
1918
+ },
1919
+ {
1920
+ "key": "agent_trust_level",
1921
+ "type": "string",
1922
+ "required": false,
1923
+ "description": "Agent trust tier: 'untrusted' | 'low' | 'verified' | 'trusted'"
1924
+ },
1925
+ {
1926
+ "key": "request_id",
1927
+ "type": "string",
1928
+ "required": true,
1929
+ "description": "Unique identifier for this request"
1930
+ },
1931
+ {
1932
+ "key": "timestamp",
1933
+ "type": "number",
1934
+ "required": true,
1935
+ "description": "Unix timestamp in milliseconds"
1936
+ },
1937
+ {
1938
+ "key": "isolation_tier",
1939
+ "type": "string",
1940
+ "required": true,
1941
+ "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."
1942
+ },
1943
+ {
1944
+ "key": "writable_paths",
1945
+ "type": "array",
1946
+ "required": false,
1947
+ "description": "Writable path prefixes the sandbox is requesting, e.g. ['/scratch']"
1948
+ },
1949
+ {
1950
+ "key": "network_egress",
1951
+ "type": "boolean",
1952
+ "required": false,
1953
+ "description": "Whether any outbound network egress is requested"
1954
+ },
1955
+ {
1956
+ "key": "egress_hosts",
1957
+ "type": "array",
1958
+ "required": false,
1959
+ "description": "Host allowlist for egress, e.g. ['pypi.org', 'files.pythonhosted.org']"
1960
+ },
1961
+ {
1962
+ "key": "exec_allowlist",
1963
+ "type": "array",
1964
+ "required": false,
1965
+ "description": "Executables the sandbox may run, e.g. ['python', 'python3']"
1966
+ },
1967
+ {
1968
+ "key": "mechanism_capabilities",
1969
+ "type": "array",
1970
+ "required": false,
1971
+ "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'."
1972
+ }
1673
1973
  ]
1674
1974
  }
1675
1975
  ]
@@ -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,30 @@ namespace AgentOps {
233
246
  "session_original_request"?: String,
234
247
  "session_max_sensitivity"?: String,
235
248
 
249
+ // Origin Surface — REQUIRED (ADR 0012 D14.2). Projected by Shield from the
250
+ // ingress product; never user-supplied. The "Applies to" narrowing target:
251
+ // policies test it with an ordinary condition (context.surface == "ai_gateway")
252
+ // — no `has` guard needed precisely because it is required. Values are the
253
+ // product identifiers: "guardrails" | "overwatch" | "ai_gateway" ("sentry"
254
+ // joins at ADR 0012 D17 phase 2). A policy with no surface condition applies
255
+ // to every surface, including ones added later (inclusive default).
256
+ "surface": String,
257
+
258
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
259
+ // All optional: guard every access with `has` — an absent-attribute read is
260
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
261
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
262
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
263
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
264
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
265
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
266
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
267
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
268
+ "flow_sink_is_external"?: Boolean,
269
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
270
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
271
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
272
+
236
273
  // Usage Budget — multi-window token & cost enforcement (optional)
237
274
  "budget_remaining_pct"?: Long,
238
275
  "budget_exceeded"?: Boolean,
@@ -247,6 +284,12 @@ namespace AgentOps {
247
284
  "budget_exceeded_daily"?: Boolean,
248
285
  "budget_exceeded_monthly"?: Boolean,
249
286
 
287
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
288
+ "rpm_remaining_pct"?: Long,
289
+ "rpm_exceeded"?: Boolean,
290
+ "tpm_remaining_pct"?: Long,
291
+ "tpm_exceeded"?: Boolean,
292
+
250
293
  // Agent Identity — authenticated agent principal metadata (optional)
251
294
  "agent_id"?: String,
252
295
  "agent_type"?: String, // "orchestrator" | "autonomous" | "tool_agent" | "human_proxy"
@@ -391,6 +434,30 @@ namespace AgentOps {
391
434
  "session_original_request"?: String,
392
435
  "session_max_sensitivity"?: String,
393
436
 
437
+ // Origin Surface — REQUIRED (ADR 0012 D14.2). Projected by Shield from the
438
+ // ingress product; never user-supplied. The "Applies to" narrowing target:
439
+ // policies test it with an ordinary condition (context.surface == "ai_gateway")
440
+ // — no `has` guard needed precisely because it is required. Values are the
441
+ // product identifiers: "guardrails" | "overwatch" | "ai_gateway" ("sentry"
442
+ // joins at ADR 0012 D17 phase 2). A policy with no surface condition applies
443
+ // to every surface, including ones added later (inclusive default).
444
+ "surface": String,
445
+
446
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
447
+ // All optional: guard every access with `has` — an absent-attribute read is
448
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
449
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
450
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
451
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
452
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
453
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
454
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
455
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
456
+ "flow_sink_is_external"?: Boolean,
457
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
458
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
459
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
460
+
394
461
  // Usage Budget (optional)
395
462
  "budget_remaining_pct"?: Long,
396
463
  "budget_exceeded"?: Boolean,
@@ -405,6 +472,12 @@ namespace AgentOps {
405
472
  "budget_exceeded_daily"?: Boolean,
406
473
  "budget_exceeded_monthly"?: Boolean,
407
474
 
475
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
476
+ "rpm_remaining_pct"?: Long,
477
+ "rpm_exceeded"?: Boolean,
478
+ "tpm_remaining_pct"?: Long,
479
+ "tpm_exceeded"?: Boolean,
480
+
408
481
  // Aggregated threat summary (optional)
409
482
  "highest_severity"?: String,
410
483
  "threat_count"?: Long,
@@ -477,6 +550,30 @@ namespace AgentOps {
477
550
  "session_original_request"?: String,
478
551
  "session_max_sensitivity"?: String,
479
552
 
553
+ // Origin Surface — REQUIRED (ADR 0012 D14.2). Projected by Shield from the
554
+ // ingress product; never user-supplied. The "Applies to" narrowing target:
555
+ // policies test it with an ordinary condition (context.surface == "ai_gateway")
556
+ // — no `has` guard needed precisely because it is required. Values are the
557
+ // product identifiers: "guardrails" | "overwatch" | "ai_gateway" ("sentry"
558
+ // joins at ADR 0012 D17 phase 2). A policy with no surface condition applies
559
+ // to every surface, including ones added later (inclusive default).
560
+ "surface": String,
561
+
562
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
563
+ // All optional: guard every access with `has` — an absent-attribute read is
564
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
565
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
566
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
567
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
568
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
569
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
570
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
571
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
572
+ "flow_sink_is_external"?: Boolean,
573
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
574
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
575
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
576
+
480
577
  // Usage Budget (optional)
481
578
  "budget_remaining_pct"?: Long,
482
579
  "budget_exceeded"?: Boolean,
@@ -491,6 +588,12 @@ namespace AgentOps {
491
588
  "budget_exceeded_daily"?: Boolean,
492
589
  "budget_exceeded_monthly"?: Boolean,
493
590
 
591
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
592
+ "rpm_remaining_pct"?: Long,
593
+ "rpm_exceeded"?: Boolean,
594
+ "tpm_remaining_pct"?: Long,
595
+ "tpm_exceeded"?: Boolean,
596
+
494
597
  // Agent Identity (optional)
495
598
  "agent_id"?: String,
496
599
  "agent_type"?: String,
@@ -559,6 +662,30 @@ namespace AgentOps {
559
662
  "session_original_request"?: String,
560
663
  "session_max_sensitivity"?: String,
561
664
 
665
+ // Origin Surface — REQUIRED (ADR 0012 D14.2). Projected by Shield from the
666
+ // ingress product; never user-supplied. The "Applies to" narrowing target:
667
+ // policies test it with an ordinary condition (context.surface == "ai_gateway")
668
+ // — no `has` guard needed precisely because it is required. Values are the
669
+ // product identifiers: "guardrails" | "overwatch" | "ai_gateway" ("sentry"
670
+ // joins at ADR 0012 D17 phase 2). A policy with no surface condition applies
671
+ // to every surface, including ones added later (inclusive default).
672
+ "surface": String,
673
+
674
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
675
+ // All optional: guard every access with `has` — an absent-attribute read is
676
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
677
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
678
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
679
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
680
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
681
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
682
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
683
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
684
+ "flow_sink_is_external"?: Boolean,
685
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
686
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
687
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
688
+
562
689
  // Usage Budget (optional)
563
690
  "budget_remaining_pct"?: Long,
564
691
  "budget_exceeded"?: Boolean,
@@ -573,6 +700,12 @@ namespace AgentOps {
573
700
  "budget_exceeded_daily"?: Boolean,
574
701
  "budget_exceeded_monthly"?: Boolean,
575
702
 
703
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
704
+ "rpm_remaining_pct"?: Long,
705
+ "rpm_exceeded"?: Boolean,
706
+ "tpm_remaining_pct"?: Long,
707
+ "tpm_exceeded"?: Boolean,
708
+
576
709
  // Agent Identity (optional)
577
710
  "agent_id"?: String,
578
711
  "agent_type"?: String,
@@ -641,6 +774,30 @@ namespace AgentOps {
641
774
  "session_original_request"?: String,
642
775
  "session_max_sensitivity"?: String,
643
776
 
777
+ // Origin Surface — REQUIRED (ADR 0012 D14.2). Projected by Shield from the
778
+ // ingress product; never user-supplied. The "Applies to" narrowing target:
779
+ // policies test it with an ordinary condition (context.surface == "ai_gateway")
780
+ // — no `has` guard needed precisely because it is required. Values are the
781
+ // product identifiers: "guardrails" | "overwatch" | "ai_gateway" ("sentry"
782
+ // joins at ADR 0012 D17 phase 2). A policy with no surface condition applies
783
+ // to every surface, including ones added later (inclusive default).
784
+ "surface": String,
785
+
786
+ // Data-Flow Labels — per-value information-flow facts (ADR 0020, optional).
787
+ // All optional: guard every access with `has` — an absent-attribute read is
788
+ // a Cedar evaluation error and an errored forbid is silently skipped (fail-open).
789
+ "flow_confidentiality"?: String, // "public" | "internal" | "confidential" | "restricted" | "unknown"
790
+ "flow_integrity"?: String, // "trusted" | "untrusted" | "mixed" | "unknown"
791
+ "flow_data_types"?: Set<String>, // "pii" | "secrets" | "source_code" | "financial" | "health" | ...
792
+ "flow_compartments"?: Set<String>, // "tenant:*" | "customer:*" | "project:*"
793
+ "flow_resolution_status"?: String, // "known" | "inferred" | "unknown" | "conflicted"
794
+ "flow_origins"?: Set<String>, // "mcp_tool_result" | "model" | "file" | "database" | "user"
795
+ "flow_sink"?: String, // "external_model" | "local_model" | "external_mcp" | "trusted_mcp" | "user_secure_output" | "public_network" | "file"
796
+ "flow_sink_is_external"?: Boolean,
797
+ "flow_sink_effects"?: Set<String>, // "network.send" | "financial.transfer" | "filesystem.write" | ...
798
+ "principal_clearances"?: Set<String>, // ADR 0020 D8 — clearances AuthN mints for the principal
799
+ "principal_compartments"?: Set<String>, // ADR 0020 D8 — compartments the principal is admitted to
800
+
644
801
  // Usage Budget (optional)
645
802
  "budget_remaining_pct"?: Long,
646
803
  "budget_exceeded"?: Boolean,
@@ -655,6 +812,12 @@ namespace AgentOps {
655
812
  "budget_exceeded_daily"?: Boolean,
656
813
  "budget_exceeded_monthly"?: Boolean,
657
814
 
815
+ // Rate Limiting — gateway-metered, Shield-decided (ADR 0014)
816
+ "rpm_remaining_pct"?: Long,
817
+ "rpm_exceeded"?: Boolean,
818
+ "tpm_remaining_pct"?: Long,
819
+ "tpm_exceeded"?: Boolean,
820
+
658
821
  // Agent Identity (optional)
659
822
  "agent_id"?: String,
660
823
  "agent_type"?: String,
@@ -663,4 +826,53 @@ namespace AgentOps {
663
826
  "agent_publisher"?: String,
664
827
 
665
828
  };
829
+
830
+ /// Context for provision_sandbox action (Forge sandbox-create envelope).
831
+ ///
832
+ /// Every capability field below is OPTIONAL and describes the envelope the
833
+ /// sandbox is being asked to provision with — Forge synthesizes it from the
834
+ /// create request attenuated by the token's scope ceiling (ADR 0019 D1),
835
+ /// then asks Cedar whether this identity may provision it. Profile templates
836
+ /// `permit` provision_sandbox only when the requested envelope stays within
837
+ /// the profile ceiling, and `forbid` any escalation beyond it.
838
+ ///
839
+ /// FAIL-OPEN WARNING (ADR 0019 D3): because these attributes are optional,
840
+ /// accessing an absent one is a Cedar *evaluation error*, and an errored
841
+ /// `forbid` is silently skipped — which fails OPEN. Every rule touching a
842
+ /// field here MUST guard it first with `has` (e.g.
843
+ /// `context has mechanism_capabilities && context.mechanism_capabilities.contains("sys:ptrace")`).
844
+ type ProvisionSandboxContext = {
845
+ // Identity (AARM R6 / CAP-IDN-011) — projected from the principal's token; optional.
846
+ "role"?: String,
847
+ "privilege_scope"?: Set<String>,
848
+ "identity_type"?: String, // Principal identity class: "human" | "agent" | "service" | "mcp_server"
849
+ "principal"?: String, // Stable principal identifier (ZeroID / WIMSE URI or user id)
850
+ "agent_trust_level"?: String, // "untrusted" | "low" | "verified" | "trusted"
851
+
852
+ // Core metadata (required)
853
+ "request_id": String,
854
+ "timestamp": Long,
855
+
856
+ // Requested isolation tier (required) — the OS-isolation tier the
857
+ // sandbox will run at, as the lowercased Forge IsolationTier name (ADR
858
+ // 0016 D1). Ordinal, weakest→strongest: "none" (trusted-local) < "os"
859
+ // (bwrap/seatbelt) < "kernel" (gVisor) < "hardware" (micro-VM + TEE).
860
+ // Templates assert a floor via set membership (e.g. a KERNEL floor =
861
+ // {"kernel","hardware"}); Forge owns the ordering.
862
+ "isolation_tier": String,
863
+
864
+ // Requested capability envelope (all optional — has-guard mandatory).
865
+ "writable_paths"?: Set<String>, // Writable path prefixes, e.g. {"/scratch"}
866
+ // Master egress switch. Forge MUST set this true whenever ANY egress is
867
+ // requested (i.e. whenever egress_hosts is non-empty), so a "no network"
868
+ // profile can gate on this single boolean. egress_hosts then narrows the
869
+ // host allowlist for profiles that DO permit egress.
870
+ "network_egress"?: Boolean,
871
+ "egress_hosts"?: Set<String>, // Host allowlist for egress, e.g. {"pypi.org"}
872
+ "exec_allowlist"?: Set<String>, // Executables the sandbox may run, e.g. {"python", "python3"}
873
+ // Curated mechanism toggles (ADR 0017 D1.3) — authorization facts only;
874
+ // NEVER raw syscalls. Allowed members: "sys:ptrace", "sys:bpf",
875
+ // "sys:raw_socket", "dev:gpu", "virt:nested".
876
+ "mechanism_capabilities"?: Set<String>,
877
+ };
666
878
  }