rezabarkhordary commited on
Commit
14e015e
·
verified ·
1 Parent(s): d731315

Create sovereign_role_scope_report.py

Browse files
Files changed (1) hide show
  1. sovereign_role_scope_report.py +254 -0
sovereign_role_scope_report.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # sovereign_role_scope_report.py
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import os
6
+ from datetime import datetime, timezone
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ from sovereign_role_scope_profile import generate_role_scope_profile
10
+
11
+
12
+ ROLE_SCOPE_OUTPUT_DIR = "sovereign_role_scope_outputs"
13
+
14
+
15
+ def _utc_now() -> str:
16
+ return datetime.now(timezone.utc).isoformat()
17
+
18
+
19
+ def _ensure_dir(path: str) -> None:
20
+ os.makedirs(path, exist_ok=True)
21
+
22
+
23
+ def _safe(v: Any, default: Any = "") -> Any:
24
+ return v if v is not None else default
25
+
26
+
27
+ def _bool_text(v: Any) -> str:
28
+ return "True" if bool(v) else "False"
29
+
30
+
31
+ def _render_header(bundle: Dict[str, Any]) -> str:
32
+ profile = bundle.get("role_scope_profile", {}) if isinstance(bundle, dict) else {}
33
+
34
+ return f"""# Sovereign Role / Scope Report
35
+
36
+ Generated at: {_safe((profile or {}).get("generated_at"), _utc_now())}
37
+
38
+ ## 1. Profile Identity
39
+ - Profile Type: {_safe(profile.get("profile_type"), "Sovereign Role Scope Profile")}
40
+ - Domain: {_safe(profile.get("domain"), "banking_and_financial_institutions")}
41
+ """
42
+
43
+
44
+ def _render_summary(bundle: Dict[str, Any]) -> str:
45
+ profile = bundle.get("role_scope_profile", {}) if isinstance(bundle, dict) else {}
46
+ summary = profile.get("summary", {}) if isinstance(profile, dict) else {}
47
+
48
+ return f"""## 2. Executive Summary
49
+ - Total Roles: {_safe(summary.get("total_roles"), 0)}
50
+ - High Sensitivity Roles: {_safe(summary.get("high_sensitivity_roles"), 0)}
51
+ - Dual-Control Roles: {_safe(summary.get("dual_control_roles"), 0)}
52
+ - Read-Only Roles: {_safe(summary.get("read_only_roles"), 0)}
53
+
54
+ ### Practical Interpretation
55
+ - Sovereign defines bounded AI role profiles rather than unbounded generic AI authority.
56
+ - High-risk banking roles are intentionally constrained with stronger review posture.
57
+ - Some roles are read-only by design and must remain non-mutating.
58
+ - Dual control is explicitly expected for sensitive execution-facing domains.
59
+ """
60
+
61
+
62
+ def _render_roles(bundle: Dict[str, Any]) -> str:
63
+ profile = bundle.get("role_scope_profile", {}) if isinstance(bundle, dict) else {}
64
+ roles = profile.get("roles", []) if isinstance(profile, dict) else []
65
+
66
+ lines: List[str] = ["## 3. Role Inventory"]
67
+
68
+ if not roles:
69
+ lines.append("- No roles recorded.")
70
+ return "\n".join(lines)
71
+
72
+ for item in roles:
73
+ allowed = item.get("allowed_actions", []) if isinstance(item, dict) else []
74
+ forbidden = item.get("forbidden_actions", []) if isinstance(item, dict) else []
75
+ scope = item.get("data_access_scope", []) if isinstance(item, dict) else []
76
+
77
+ lines.append(f"### {item.get('role', 'unknown_role')}")
78
+ lines.append(f"- Status: {_safe(item.get('status'))}")
79
+ lines.append(f"- Business Domain: {_safe(item.get('business_domain'))}")
80
+ lines.append(f"- Sensitivity Boundary: {_safe(item.get('sensitivity_boundary'))}")
81
+ lines.append(f"- Review Expectation: {_safe(item.get('review_expectation'))}")
82
+ lines.append(f"- Dual Control Required: {_bool_text(item.get('dual_control_required'))}")
83
+
84
+ if allowed:
85
+ lines.append("- Allowed Actions:")
86
+ for x in allowed:
87
+ lines.append(f" - {x}")
88
+
89
+ if forbidden:
90
+ lines.append("- Forbidden Actions:")
91
+ for x in forbidden:
92
+ lines.append(f" - {x}")
93
+
94
+ if scope:
95
+ lines.append("- Data Access Scope:")
96
+ for x in scope:
97
+ lines.append(f" - {x}")
98
+
99
+ lines.append("")
100
+
101
+ return "\n".join(lines).rstrip() + "\n"
102
+
103
+
104
+ def _render_principles(bundle: Dict[str, Any]) -> str:
105
+ profile = bundle.get("role_scope_profile", {}) if isinstance(bundle, dict) else {}
106
+ principles = profile.get("global_principles", []) if isinstance(profile, dict) else []
107
+
108
+ lines: List[str] = ["## 4. Global Role-Scope Principles"]
109
+
110
+ if not principles:
111
+ lines.append("- No global principles recorded.")
112
+ return "\n".join(lines)
113
+
114
+ for item in principles:
115
+ lines.append(f"### {item.get('principle', 'unknown_principle')}")
116
+ lines.append(f"- Status: {_safe(item.get('status'))}")
117
+ lines.append(f"- Description: {_safe(item.get('description'))}")
118
+ lines.append("")
119
+
120
+ return "\n".join(lines).rstrip() + "\n"
121
+
122
+
123
+ def _render_governance_interpretation(bundle: Dict[str, Any]) -> str:
124
+ profile = bundle.get("role_scope_profile", {}) if isinstance(bundle, dict) else {}
125
+ roles = profile.get("roles", []) if isinstance(profile, dict) else []
126
+
127
+ dual_control_roles = [r.get("role") for r in roles if bool(r.get("dual_control_required"))]
128
+ read_only_roles = [r.get("role") for r in roles if "read_only" in str(r.get("role", "")).lower()]
129
+
130
+ lines = ["## 5. Governance Interpretation"]
131
+
132
+ if dual_control_roles:
133
+ lines.append("- Roles Expecting Dual Control:")
134
+ for role in dual_control_roles:
135
+ lines.append(f" - {role}")
136
+ else:
137
+ lines.append("- No dual-control roles recorded.")
138
+
139
+ if read_only_roles:
140
+ lines.append("- Read-Only Roles:")
141
+ for role in read_only_roles:
142
+ lines.append(f" - {role}")
143
+ else:
144
+ lines.append("- No read-only roles recorded.")
145
+
146
+ lines.append("- High-risk banking execution domains should not silently inherit broad autonomous authority.")
147
+ lines.append("- Support, audit, and analysis roles should remain bound to their declared scope.")
148
+ lines.append("- Payment and treasury-like roles require proportional runtime control and review posture.")
149
+
150
+ return "\n".join(lines)
151
+
152
+
153
+ def _render_artifact_status(bundle: Dict[str, Any]) -> str:
154
+ seal = bundle.get("crypto_seal", {}) if isinstance(bundle, dict) else {}
155
+
156
+ return f"""## 6. Artifact Status
157
+ - Sealed: {bool(bundle.get("sealed", False))}
158
+ - Seal Digest: {_safe(seal.get("seal_digest"), "")}
159
+ - Seal Scheme: {_safe(seal.get("scheme"), "")}
160
+ - Seal Algorithm: {_safe(seal.get("algorithm"), "")}
161
+ - Signer Hint: {_safe(seal.get("signer_hint"), "")}
162
+ """
163
+
164
+
165
+ def _render_verdict(bundle: Dict[str, Any]) -> str:
166
+ profile = bundle.get("role_scope_profile", {}) if isinstance(bundle, dict) else {}
167
+ notes = profile.get("notes", []) if isinstance(profile, dict) else []
168
+
169
+ verdict = (
170
+ "Sovereign currently expresses a bounded bank-grade role model: "
171
+ "AI roles are scoped by business function, high-risk roles are constrained, "
172
+ "and role support does not imply unbounded autonomous execution authority."
173
+ )
174
+
175
+ lines = [
176
+ "## 7. Preliminary Bank-Facing Verdict",
177
+ verdict,
178
+ "",
179
+ "## 8. Notes",
180
+ ]
181
+
182
+ if notes:
183
+ for item in notes:
184
+ lines.append(f"- {item}")
185
+ else:
186
+ lines.append("- No additional notes provided.")
187
+
188
+ return "\n".join(lines)
189
+
190
+
191
+ def build_role_scope_markdown(bundle: Dict[str, Any]) -> str:
192
+ parts = [
193
+ _render_header(bundle),
194
+ _render_summary(bundle),
195
+ _render_roles(bundle),
196
+ _render_principles(bundle),
197
+ _render_governance_interpretation(bundle),
198
+ _render_artifact_status(bundle),
199
+ _render_verdict(bundle),
200
+ ]
201
+ return "\n\n".join(parts).strip() + "\n"
202
+
203
+
204
+ def save_role_scope_report(
205
+ bundle: Dict[str, Any],
206
+ output_dir: str = ROLE_SCOPE_OUTPUT_DIR,
207
+ base_name: Optional[str] = None,
208
+ ) -> Dict[str, str]:
209
+ _ensure_dir(output_dir)
210
+
211
+ ts = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
212
+ base = base_name or f"sovereign_role_scope_report_{ts}"
213
+
214
+ json_path = os.path.join(output_dir, f"{base}.json")
215
+ md_path = os.path.join(output_dir, f"{base}.md")
216
+
217
+ with open(json_path, "w", encoding="utf-8") as f:
218
+ json.dump(bundle, f, ensure_ascii=False, indent=2)
219
+
220
+ markdown = build_role_scope_markdown(bundle)
221
+ with open(md_path, "w", encoding="utf-8") as f:
222
+ f.write(markdown)
223
+
224
+ return {
225
+ "json_report": json_path,
226
+ "markdown_report": md_path,
227
+ }
228
+
229
+
230
+ def generate_role_scope_report(
231
+ output_dir: str = ROLE_SCOPE_OUTPUT_DIR,
232
+ base_name: Optional[str] = None,
233
+ ) -> Dict[str, Any]:
234
+ bundle = generate_role_scope_profile()
235
+
236
+ files = save_role_scope_report(
237
+ bundle=bundle,
238
+ output_dir=output_dir,
239
+ base_name=base_name,
240
+ )
241
+
242
+ return {
243
+ "ok": True,
244
+ "generated_at": _utc_now(),
245
+ "bundle": bundle,
246
+ "files": files,
247
+ }
248
+
249
+
250
+ if __name__ == "__main__":
251
+ out = generate_role_scope_report()
252
+ print(json.dumps(out, indent=2, ensure_ascii=False))
253
+
254
+