icdev-core 0.2.1__py3-none-any.whl

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.
@@ -0,0 +1,521 @@
1
+ # CUI // SP-CTI
2
+ # GENERATED by `python tools/db/schema_ownership.py --regenerate` from
3
+ # args/schema_ownership_rules.yaml -- do not edit by hand; change a rule.
4
+ # Tables owned by the domain-neutral core (xit-decl-04). `rls: true` means the
5
+ # row-security predicate applies; an explicit false is the generalisation of
6
+ # get_canvas_connection. `declared_in` lists up to four declaring sources.
7
+ rls_exempt: []
8
+ tables:
9
+ a2a_discovery_registry: core
10
+ a2a_task_artifacts: core
11
+ a2a_task_history: core
12
+ a2a_tasks: core
13
+ ace_agent_workflows: core
14
+ ace_artifacts: core
15
+ ace_audit_log: core
16
+ ace_coworker_memory: core
17
+ ace_coworkers: core
18
+ ace_event_results: core
19
+ ace_events: core
20
+ ace_instances: core
21
+ ace_messages: core
22
+ ace_sessions: core
23
+ ace_skill_candidates: core
24
+ ace_step_audit_log: core
25
+ ace_step_transitions: core
26
+ ace_team_suggestions: core
27
+ ace_trust_ledger: core
28
+ ace_webhook_log: core
29
+ activity_tasks: core
30
+ agent_a2a_tasks: core
31
+ agent_approval_log: core
32
+ agent_benchmark_results: core
33
+ agent_chat_turns: core
34
+ agent_collaboration_history: core
35
+ agent_coordination: core
36
+ agent_cron_jobs: core
37
+ agent_cron_runs: core
38
+ agent_eval_runs: core
39
+ agent_evals: core
40
+ agent_execution_traces: core
41
+ agent_executions: core
42
+ agent_findings: core
43
+ agent_hitl_pending: core
44
+ agent_improvement_artifacts: core
45
+ agent_loop_checkpoints: core
46
+ agent_loop_sessions: core
47
+ agent_mailbox: core
48
+ agent_memory: core
49
+ agent_memory_transfer_log: core
50
+ agent_output_violations: core
51
+ agent_registry: core
52
+ agent_scoped_memory: core
53
+ agent_session_events: core
54
+ agent_session_policy_state: core
55
+ agent_sessions: core
56
+ agent_subtasks: core
57
+ agent_task_leases: core
58
+ agent_token_budgets: core
59
+ agent_token_usage: core
60
+ agent_topology_snapshots: core
61
+ agent_trust_scores: core
62
+ agent_unattended_sessions: core
63
+ agent_vetoes: core
64
+ agent_wakes: core
65
+ agent_workflows: core
66
+ agentic_fitness_assessments: core
67
+ agents: core
68
+ ai_telemetry: core
69
+ alerts: core
70
+ anvil_critique_findings: core
71
+ anvil_critique_sessions: core
72
+ audit: core
73
+ audit_chain_genesis: core
74
+ audit_platform: core
75
+ audit_trail: core
76
+ audit_trail_archive: core
77
+ auto_consolidate_runs: core
78
+ auto_resolution_log: core
79
+ autonomy_actions: core
80
+ autonomy_behavior_log: core
81
+ autonomy_observations: core
82
+ autonomy_trust_state: core
83
+ awareness_learned_edges: core
84
+ awareness_run_log: core
85
+ batch_run_steps: core
86
+ batch_runs: core
87
+ bayesian_experiment_scores: core
88
+ bayesian_teaching_scores: core
89
+ blueprint_digests: core
90
+ canvas_access_grants: core
91
+ canvas_ai_decisions: core
92
+ canvas_events: core
93
+ canvas_instances: core
94
+ canvas_kg_build_log: core
95
+ canvas_kg_edges: core
96
+ canvas_kg_nodes: core
97
+ canvas_kg_queries: core
98
+ canvas_projects: core
99
+ capability_evaluations: core
100
+ capability_genome: core
101
+ centralized_logs: core
102
+ chat_contexts: core
103
+ chat_corrections: core
104
+ chat_intake_sessions: core
105
+ chat_messages: core
106
+ chat_tasks: core
107
+ child_app_registry: core
108
+ child_app_telemetry: core
109
+ child_capabilities: core
110
+ child_learned_behaviors: core
111
+ child_telemetry: core
112
+ ci_conversation_turns: core
113
+ ci_conversations: core
114
+ ci_event_queue: core
115
+ ci_pipeline_runs: core
116
+ ci_worktrees: core
117
+ code_quality_findings: core
118
+ code_quality_metrics: core
119
+ code_reviews: core
120
+ codebase_index: core
121
+ codebase_qa_cache: core
122
+ coherence_baseline: core
123
+ component_audit_log: core
124
+ component_heal_log: core
125
+ confabulation_checks: core
126
+ context_pressure_events: core
127
+ cortex_audit: core
128
+ cortex_chat_sessions: core
129
+ cortex_entity_findings: core
130
+ cortex_finding_runs: core
131
+ cortex_messages: core
132
+ cortex_search_history: core
133
+ cortex_service_keys: core
134
+ cortex_sessions: core
135
+ coworker_dic_contexts: core
136
+ creative_competitors: core
137
+ creative_feature_gaps: core
138
+ creative_gap: core
139
+ creative_gaps: core
140
+ creative_pain_points: core
141
+ creative_signals: core
142
+ creative_specs: core
143
+ creative_trends: core
144
+ credential_active_tokens: core
145
+ credential_broker_log: core
146
+ cross_agency_transfers: core
147
+ cross_pollination_proposals: core
148
+ daily_logs: core
149
+ dashboard_api_keys: core
150
+ dashboard_auth_log: core
151
+ dashboard_user_llm_keys: core
152
+ dashboard_users: core
153
+ dashboard_users_new: core
154
+ data_classifications: core
155
+ databridge_agent_access_log: core
156
+ db_agents: core
157
+ db_connections: core
158
+ db_connector_configs: core
159
+ db_forge_connectors: core
160
+ db_forge_promotions: core
161
+ db_forge_sandbox_log: core
162
+ db_forge_specs: core
163
+ db_forge_validations: core
164
+ db_inferred_schemas: core
165
+ db_lookup_tables: core
166
+ db_mapping_log: core
167
+ db_mappings: core
168
+ db_message_routing: core
169
+ db_messages: core
170
+ db_messaging_daemon_state: core
171
+ db_oauth_tokens: core
172
+ db_schemas: core
173
+ db_storage_paths: core
174
+ db_streams: core
175
+ db_sync_log: core
176
+ dd_anomaly_runs: core
177
+ dd_freshness_alerts: core
178
+ dependency_inventory: core
179
+ dependency_vulnerabilities: core
180
+ deployments: core
181
+ dev_profile_detections: core
182
+ dev_profile_locks: core
183
+ dev_profiles: core
184
+ developer_scorecards: core
185
+ developer_scorecards__343: core
186
+ deviation_rule_events: core
187
+ devsecops_pipeline_audit: core
188
+ devsecops_profiles: core
189
+ dispatcher_mode_overrides: core
190
+ egress_policy_audit: core
191
+ encryption_key_history: core
192
+ encryption_key_log: core
193
+ encryption_keys: core
194
+ entity_currency: core
195
+ evolution_audit: core
196
+ evolution_reflex_state: core
197
+ experiment_candidates: core
198
+ experiment_landscapes: core
199
+ experiment_programs: core
200
+ experiment_results: core
201
+ extension_execution_log: core
202
+ extension_registry: core
203
+ failure_log: core
204
+ finding_approvals: core
205
+ finding_replay_attempts: core
206
+ forge_hub_ratings: core
207
+ forge_hub_trust_scores: core
208
+ ft_active_models: core
209
+ ft_dataset_examples: core
210
+ ft_datasets: core
211
+ ft_evaluations: core
212
+ ft_hp_searches: core
213
+ ft_hp_trials: core
214
+ ft_hyperparam_results: core
215
+ ft_model_versions: core
216
+ ft_pipeline_runs: core
217
+ ft_promotion_log: core
218
+ ft_quality_snapshots: core
219
+ ft_training_job_events: core
220
+ ft_training_jobs: core
221
+ ft_training_pairs: core
222
+ ft_trajectories: core
223
+ ft_trajectory_steps: core
224
+ gateway_rate_limits: core
225
+ genesis_audit: core
226
+ genesis_audit_log: core
227
+ genesis_convergence_log: core
228
+ genesis_designs: core
229
+ genesis_generated_goals: core
230
+ genesis_gkp: core
231
+ genesis_knowledge_packets: core
232
+ genesis_learned_goal_versions: core
233
+ genesis_learned_goals: core
234
+ genesis_outputs: core
235
+ genesis_phase_log: core
236
+ genesis_reflex_log: core
237
+ genesis_reflex_state: core
238
+ genesis_reflexes: core
239
+ genesis_runs: core
240
+ genesis_stagnation_log: core
241
+ genesis_tool_patterns: core
242
+ genome_versions: core
243
+ gitlab_inbox: core
244
+ gitlab_pipeline_runs: core
245
+ gitlab_task_claims: core
246
+ group_members: core
247
+ group_roles: core
248
+ groups: core
249
+ h: core
250
+ heartbeat_checks: core
251
+ hitl_intake_pending: core
252
+ hook_events: core
253
+ icd_documents: core
254
+ icdev_capability_map: core
255
+ icdev_qa_messages: core
256
+ icdev_qa_sessions: core
257
+ indicator_baselines: core
258
+ indicator_scores: core
259
+ innovation_competitor_scans: core
260
+ innovation_feedback: core
261
+ innovation_signal: core
262
+ innovation_signals: core
263
+ innovation_solutions: core
264
+ innovation_standards_updates: core
265
+ innovation_trends: core
266
+ innovation_triage_log: core
267
+ insider_risk_baselines: core
268
+ insider_risk_scores: core
269
+ integrity_assessments: core
270
+ integrity_authorizations: core
271
+ integrity_capabilities: core
272
+ integrity_findings: core
273
+ integrity_verdicts: core
274
+ isa_agreements: core
275
+ kanban_alert_queue: core
276
+ kanban_board_settings: core
277
+ kanban_executions: core
278
+ kanban_status_transitions: core
279
+ kanban_tags: core
280
+ kanban_task_comments: core
281
+ kanban_task_deps: core
282
+ kanban_task_revivals: core
283
+ kanban_task_subscriptions: core
284
+ kanban_task_tags: core
285
+ kanban_tasks: core
286
+ kanban_tasks_backup: core
287
+ kanban_tasks_old_016: core
288
+ kanban_triage_log: core
289
+ kanban_verifications: core
290
+ kg_edges: core
291
+ kg_graphs: core
292
+ kg_nodes: core
293
+ kg_ontology: core
294
+ kg_ontology_mappings: core
295
+ kg_retrieval_log: core
296
+ knowledge_graph_edges: core
297
+ knowledge_patterns: core
298
+ llm_chain_telemetry: core
299
+ llm_context_compression_log: core
300
+ llm_cost_alerts: core
301
+ llm_cost_recommendations: core
302
+ llm_gateway_audit: core
303
+ llm_gateway_rate_limits: core
304
+ llm_judge_evaluations: core
305
+ llm_proxy_key_audit: core
306
+ llm_proxy_keys: core
307
+ llm_proxy_spend: core
308
+ llm_proxy_team_limits: core
309
+ llm_proxy_team_usage: core
310
+ llm_response_cache: core
311
+ llm_rl_qtable: core
312
+ log_health_metrics: core
313
+ maintenance_audits: core
314
+ marketplace_assets: core
315
+ marketplace_dependencies: core
316
+ marketplace_embeddings: core
317
+ marketplace_installations: core
318
+ marketplace_ratings: core
319
+ marketplace_reviews: core
320
+ marketplace_scan_results: core
321
+ marketplace_versions: core
322
+ mcp_tool_registry: core
323
+ memory_access_log: core
324
+ memory_buffer: core
325
+ memory_consolidation_log: core
326
+ memory_entity_relationships: core
327
+ memory_entries: core
328
+ memory_fts: core
329
+ metric_snapshots: core
330
+ module_budget_periods: core
331
+ module_budget_usage: core
332
+ nlq_queries: core
333
+ notification_escalations: core
334
+ notification_log: core
335
+ notification_preferences: core
336
+ ontology_alignments: core
337
+ ontology_catalog: core
338
+ ontology_classes: core
339
+ ontology_federation_meta: core
340
+ ontology_properties: core
341
+ ontology_subclass_closure: core
342
+ openclaw_exports: core
343
+ openclaw_imports: core
344
+ oracle_convergence_events: core
345
+ oracle_health_history: core
346
+ oracle_lens_state: core
347
+ oracle_predictions: core
348
+ oracle_remediation_proposals: core
349
+ otel_spans: core
350
+ otel_spans_archive: core
351
+ outcome_verification_log: core
352
+ pr_intelligence_reports: core
353
+ pr_merge_eligibility_events: core
354
+ production_audits: core
355
+ projects: core
356
+ prompt_ab_tests: core
357
+ prompt_audit_log: core
358
+ prompt_chain_executions: core
359
+ prompt_injection_log: core
360
+ prompt_versions: core
361
+ propagation_log: core
362
+ propagation_verifications: core
363
+ prov_activities: core
364
+ prov_activities_archive: core
365
+ prov_entities: core
366
+ prov_entities_archive: core
367
+ prov_relations: core
368
+ prov_relations_archive: core
369
+ quality_gkps: core
370
+ quality_snapshots: core
371
+ quality_trends: core
372
+ rag_chunk_summaries: core
373
+ rag_chunks: core
374
+ rag_citations: core
375
+ rag_compliance_corpus: core
376
+ rag_evaluation_campaigns: core
377
+ rag_evaluation_results: core
378
+ rag_evaluations: core
379
+ rag_ingestion_log: core
380
+ rag_kg_backfill_cursor: core
381
+ rag_parent_cache: core
382
+ rag_pdf_documents: core
383
+ rag_provenance_ledger: core
384
+ rag_queries: core
385
+ rag_retrieval_log: core
386
+ redaction_audit: core
387
+ redaction_registry: core
388
+ reflex_observations: core
389
+ remediation_actions: core
390
+ remediation_audit_log: core
391
+ remote_agent_sessions: core
392
+ remote_command_allowlist: core
393
+ remote_command_log: core
394
+ remote_user_bindings: core
395
+ requirements: core
396
+ research_build_buy: core
397
+ research_cache: core
398
+ research_capability_map: core
399
+ research_challenges: core
400
+ research_dossiers: core
401
+ research_forecasts: core
402
+ research_regulatory_map: core
403
+ research_sessions: core
404
+ research_signals: core
405
+ research_trends: core
406
+ research_verticals: core
407
+ review_board_audit: core
408
+ review_board_findings: core
409
+ review_board_health_history: core
410
+ review_board_reflex_state: core
411
+ review_board_remediation_log: core
412
+ review_traceability: core
413
+ runtime_feedback: core
414
+ runtime_invocations: core
415
+ safe_decomposition: core
416
+ sandbox_execution_log: core
417
+ scaffold_runs: core
418
+ schema_migrations: core
419
+ sdc_compliance_timeline: core
420
+ sdc_roi_metrics: core
421
+ sdc_workflow_step_runs: core
422
+ security_framework_status: core
423
+ security_policies: core
424
+ self_heal_project_patterns: core
425
+ self_healing_events: core
426
+ self_healing_patterns: core
427
+ session_purposes: core
428
+ session_risk_log: core
429
+ sg_coa_options: core
430
+ sg_conflict_events: core
431
+ sg_hitl_items: core
432
+ sg_pir_requirements: core
433
+ sg_prioritized_signals: core
434
+ sg_raw_signals: core
435
+ sg_raw_signals_audit: core
436
+ sg_red_cell_assessments: core
437
+ sg_sio_assessments: core
438
+ smart_encoding_dictionary: core
439
+ source_citation_registry: core
440
+ staging_environments: core
441
+ statement: core
442
+ stub_detection_results: core
443
+ studio_automation_runs: core
444
+ studio_automations: core
445
+ studio_case_history: core
446
+ studio_case_types: core
447
+ studio_cases: core
448
+ studio_dashboards: core
449
+ studio_event_sources: core
450
+ studio_form_submissions: core
451
+ studio_forms: core
452
+ studio_mcp_dispatch_audit: core
453
+ studio_run_memory: core
454
+ studio_trigger_events: core
455
+ studio_workflow_heal_log: core
456
+ studio_workflow_run_steps: core
457
+ studio_workflow_runs: core
458
+ studio_workflow_triggers: core
459
+ studio_workflows: core
460
+ system_cards: core
461
+ t: core
462
+ t_new: core
463
+ tasks: core
464
+ tenant_component_overrides: core
465
+ tenant_llm_keys: core
466
+ tenant_zone_assignments: core
467
+ thread_heatmap_snapshots: core
468
+ tool_chain_events: core
469
+ tsp_documents: core
470
+ ungated_test_baseline: core
471
+ use_case_chains: core
472
+ use_case_overrides: core
473
+ user_challenges: core
474
+ user_clearances: core
475
+ user_compartments: core
476
+ user_daily_briefings: core
477
+ user_identity_profiles: core
478
+ user_integrations: core
479
+ user_knowledge_items: core
480
+ user_mfa: core
481
+ user_objectives: core
482
+ user_preferences: core
483
+ user_relationship_interactions: core
484
+ user_relationships: core
485
+ users: core
486
+ vsm_dora_snapshots: core
487
+ vsm_stage_events: core
488
+ watchdog_alerts: core
489
+ watchdog_state: core
490
+ wf_approvals: core
491
+ wf_citations: core
492
+ wf_document_submissions: core
493
+ wf_document_templates: core
494
+ wf_external_steps: core
495
+ wf_feedback: core
496
+ wf_feedback_insights: core
497
+ wf_generated_reports: core
498
+ wf_ingested_files: core
499
+ wf_instances: core
500
+ wf_report_section_chunks: core
501
+ wf_report_section_defs: core
502
+ wf_team_assignments: core
503
+ wf_team_members: core
504
+ wf_teams: core
505
+ wf_templates: core
506
+ wg_analysis_findings: core
507
+ wg_analysis_results: core
508
+ wg_batch_runs: core
509
+ wg_board_decisions: core
510
+ wg_glossary: core
511
+ wg_glossary_new: core
512
+ wg_snippets: core
513
+ wg_style_guide_locks: core
514
+ wg_style_guides: core
515
+ wg_style_profiles: core
516
+ workflow_acceptance_criteria: core
517
+ workflow_handoffs: core
518
+ workflow_loops: core
519
+ workflow_reconciliations: core
520
+ workflow_replay_sessions: core
521
+ workflow_tasks: core
@@ -0,0 +1,148 @@
1
+ # CUI // SP-CTI
2
+ """The sensitivity model a parent declares -- ONE place for labels the kernel gates on.
3
+
4
+ Today the classification lattice is hard-coded four times in this tree and the
5
+ copies disagree (``tools/compliance/classification_manager.py::
6
+ get_clearance_order``, ``tools/security/security_context.py``,
7
+ ``tools/security/middleware.py`` and ``tools/llm/proxy_gateway.py::
8
+ _CLEARANCE_ORDER`` -- SECRET is rank 3 in one and 4 in another, and the LLM
9
+ router treats ``LLMRequest.classification`` as an IL level at one site and as a
10
+ label at another). ``args/classification_profiles.yaml`` is a per-level
11
+ feature-flag profile with no dominance order at all.
12
+
13
+ This module reads the ``sensitivity:`` block of the parent's
14
+ ``icdev_domain.yaml`` (xit-decl-01) and answers:
15
+
16
+ * :func:`label_column` -- the row-security column (``classification``)
17
+ * :func:`labels` -- the declared labels, LOWEST to HIGHEST
18
+ * :func:`default_label` -- what an unlabelled row or request is
19
+ * :func:`is_egress_restricted(label)`
20
+ * :func:`rank(label)` -- position in the declared order (unknown -> None)
21
+ * :func:`dominates(a, b)` -- may clearance ``a`` read rows labelled ``b``
22
+ * :func:`rls_exempt_tables` -- the generated ownership manifest's opt-outs
23
+
24
+ For ICDEV[IT] the declared order reproduces the runtime ladder the row-security
25
+ layer actually enforces today (``public < unclassified < cui < eci < secret <
26
+ top_secret < top_secret_sci``); ICDEV[FT] declares ``public < internal < pii <
27
+ mnpi < account_secret`` and no IL levels. Labels are compared case-insensitively
28
+ with ``//`` and spaces folded to ``_`` (``"TOP SECRET//SCI"`` -> ``top_secret_sci``).
29
+
30
+ CONSUMERS ARE NOT REWIRED HERE. xit-core-* moves the router's egress gate, the
31
+ RLS predicate builder and the citation-grounding default onto this module one
32
+ PR at a time, each asserted behaviour-identical for IT. This task ships the
33
+ seam and the tests that pin what the seam says.
34
+ """
35
+ from __future__ import annotations
36
+
37
+ import os
38
+ from functools import lru_cache
39
+ from pathlib import Path
40
+
41
+ from icdev.core.domain import Domain, load_domain
42
+ from icdev.core.paths import repo_root
43
+
44
+ #: The order the row-security layer enforces for ICDEV[IT] today, used when a
45
+ #: declaration lists no ``order:``; mirrors security_context._CLASSIFICATION_LABELS.
46
+ _IT_RUNTIME_ORDER = ("public", "unclassified", "cui", "eci", "secret", "top_secret", "top_secret_sci")
47
+
48
+
49
+ def normalise(label: str | None) -> str:
50
+ if label is None:
51
+ return ""
52
+ s = str(label).strip().lower().replace("//", "_").replace("/", "_").replace(" ", "_").replace("-", "_")
53
+ while "__" in s:
54
+ s = s.replace("__", "_")
55
+ return s
56
+
57
+
58
+ def _domain(domain: Domain | None = None) -> Domain:
59
+ return domain or load_domain()
60
+
61
+
62
+ def label_column(domain: Domain | None = None) -> str:
63
+ return _domain(domain).sensitivity.column or "classification"
64
+
65
+
66
+ def labels(domain: Domain | None = None) -> tuple[str, ...]:
67
+ """Declared labels, lowest to highest. ``order:`` wins; else ``levels``/IT runtime order."""
68
+ dom = _domain(domain)
69
+ raw = (dom.raw.get("sensitivity") or {}) if dom.raw else {}
70
+ order = raw.get("order")
71
+ if order:
72
+ return tuple(normalise(x) for x in order)
73
+ if dom.key == "it":
74
+ return _IT_RUNTIME_ORDER
75
+ # FT and any other domain: egress_restricted are the HIGH end, default the low end
76
+ low = [normalise(dom.sensitivity.default)]
77
+ high = [normalise(x) for x in dom.sensitivity.egress_restricted]
78
+ return tuple(dict.fromkeys(low + high))
79
+
80
+
81
+ def default_label(domain: Domain | None = None) -> str:
82
+ return normalise(_domain(domain).sensitivity.default) or "public"
83
+
84
+
85
+ def is_egress_restricted(label: str | None, domain: Domain | None = None) -> bool:
86
+ """May data carrying ``label`` leave the enclave (reach a remote provider)?
87
+
88
+ Unknown labels are restricted -- fail closed, the same answer
89
+ proxy_gateway gives (rank 99).
90
+ """
91
+ dom = _domain(domain)
92
+ n = normalise(label) if label else default_label(dom)
93
+ restricted = {normalise(x) for x in dom.sensitivity.egress_restricted}
94
+ if n in restricted:
95
+ return True
96
+ return n not in labels(dom)
97
+
98
+
99
+ def rank(label: str | None, domain: Domain | None = None) -> int | None:
100
+ order = labels(domain)
101
+ n = normalise(label) if label else default_label(domain)
102
+ return order.index(n) if n in order else None
103
+
104
+
105
+ def dominates(clearance: str | None, row_label: str | None, domain: Domain | None = None) -> bool:
106
+ """May ``clearance`` read a row labelled ``row_label``? Unknown on either side -> False."""
107
+ a, b = rank(clearance, domain), rank(row_label, domain)
108
+ if a is None or b is None:
109
+ return False
110
+ return a >= b
111
+
112
+
113
+ @lru_cache(maxsize=1)
114
+ def _manifest_exempt(root: str) -> frozenset[str]:
115
+ import yaml # noqa: PLC0415
116
+
117
+ out: set[str] = set()
118
+ for rel in (Path("icdev") / "core" / "schema" / "tables.yaml", Path("tools") / "db" / "schema" / "tables.yaml"):
119
+ p = Path(root) / rel
120
+ if not p.is_file():
121
+ continue
122
+ try:
123
+ data = yaml.safe_load(p.read_text(encoding="utf-8")) or {}
124
+ except Exception: # noqa: BLE001 -- an unreadable manifest exempts nothing
125
+ continue
126
+ out.update(str(t) for t in (data.get("rls_exempt") or []))
127
+ return frozenset(out)
128
+
129
+
130
+ def rls_exempt_tables(domain: Domain | None = None) -> frozenset[str]:
131
+ """Tables the row-security predicate is NOT injected into (manifest ``rls_exempt``)."""
132
+ root = str(_domain(domain).root if domain else repo_root())
133
+ if os.environ.get("ICDEV_RLS_EXEMPT_DISABLE", "").strip().lower() in ("1", "true", "yes"):
134
+ return frozenset()
135
+ return _manifest_exempt(root)
136
+
137
+
138
+ def describe(domain: Domain | None = None) -> dict:
139
+ dom = _domain(domain)
140
+ return {
141
+ "domain": dom.key,
142
+ "column": label_column(dom),
143
+ "default": default_label(dom),
144
+ "labels": list(labels(dom)),
145
+ "egress_restricted": [normalise(x) for x in dom.sensitivity.egress_restricted],
146
+ "levels": list(dom.sensitivity.levels),
147
+ "rls_exempt_tables": sorted(rls_exempt_tables(dom)),
148
+ }