Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions src/31_Profiles/governance_privacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@
from pathlib import Path
from typing import Any
import hashlib, json, secrets, sqlite3, time
from contextlib import contextmanager


@contextmanager
def dbctx(path):
db = sqlite3.connect(path)
try:
yield db
db.commit()
except Exception:
db.rollback()
raise
finally:
db.close()

def now_ms(): return int(time.time() * 1000)
def canon(v): return json.dumps(v, sort_keys=True, separators=(",", ":"), ensure_ascii=False, default=str).encode()
Expand Down Expand Up @@ -48,7 +62,7 @@ class DisputeLedger:
KINDS = {"CLAIM", "CHALLENGE", "EVIDENCE", "RULING", "SUPERSESSION", "CONSEQUENCE"}
def __init__(self, root: str | Path, identity):
self.path = Path(root) / "entity_v3_disputes.sqlite"; self.identity = identity
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("""CREATE TABLE IF NOT EXISTS records(
record_id TEXT PRIMARY KEY, kind TEXT NOT NULL, actor_entity_id TEXT NOT NULL,
subject_ref TEXT NOT NULL, target_ref TEXT, payload_json TEXT NOT NULL,
Expand All @@ -68,15 +82,15 @@ def record(self, kind: str, actor: str, subject_ref: str, payload: dict,
"authority_basis": authority_basis, "created_at_ms": now_ms(),
"history_rewrite_prohibited": True}
sig = self.identity.sign(actor, body)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("INSERT INTO records VALUES(?,?,?,?,?,?,?,?,?)", (
body["record_id"], kind, actor, body["subject_ref"], target_ref,
json.dumps(body["payload"], sort_keys=True), authority_basis,
body["created_at_ms"], json.dumps(sig, sort_keys=True)))
return dict(body, signature=sig)

def state(self, subject_ref: str) -> dict:
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
rows = db.execute("SELECT * FROM records WHERE subject_ref=? ORDER BY created_at_ms,record_id",
(subject_ref,)).fetchall()
Expand All @@ -95,7 +109,7 @@ class StatusTimeProfile:
"""Signed time/status objects with deterministic stale and revocation behaviour."""
def __init__(self, root: str | Path, identity):
self.path = Path(root) / "entity_v3_status_time.sqlite"; self.identity = identity
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("""CREATE TABLE IF NOT EXISTS statuses(
status_id TEXT PRIMARY KEY, subject_ref TEXT NOT NULL, issuer TEXT NOT NULL,
state TEXT NOT NULL, epoch INTEGER NOT NULL, effective_at_ms INTEGER NOT NULL,
Expand All @@ -116,7 +130,7 @@ def publish_status(self, issuer: str, subject_ref: str, state: str, *, epoch: in
if stale_policy not in {"FAIL_CLOSED", "READ_ONLY_GRACE", "ALLOW_UNTIL_EXPIRY"}:
raise ValueError("invalid stale policy")
effective = int(effective_at_ms or now_ms()); expires = effective + max(1, int(ttl_ms))
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
latest = db.execute("SELECT COALESCE(MAX(epoch),-1) FROM statuses WHERE subject_ref=?",
(subject_ref,)).fetchone()[0]
if int(epoch) <= int(latest): raise ValueError("status epoch must increase")
Expand All @@ -125,15 +139,15 @@ def publish_status(self, issuer: str, subject_ref: str, state: str, *, epoch: in
"effective_at_ms": effective, "expires_at_ms": expires, "stale_policy": stale_policy,
"created_at_ms": now_ms()}
sig = self.identity.sign(issuer, body)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("INSERT INTO statuses VALUES(?,?,?,?,?,?,?,?,?,?)", (
body["status_id"], subject_ref, issuer, state, int(epoch), effective, expires,
stale_policy, body["created_at_ms"], json.dumps(sig, sort_keys=True)))
return dict(body, signature=sig)

def evaluate(self, subject_ref: str, *, at_ms=None) -> dict:
at = int(at_ms or now_ms())
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
row = db.execute("SELECT * FROM statuses WHERE subject_ref=? AND effective_at_ms<=? "
"ORDER BY epoch DESC LIMIT 1", (subject_ref, at)).fetchone()
Expand All @@ -154,7 +168,7 @@ class RecoveryQuorum:
"""Multi-party approval gate wrapped around the existing cryptographic recovery mechanism."""
def __init__(self, root: str | Path, identity):
self.path = Path(root) / "entity_v3_recovery_quorum.sqlite"; self.identity = identity
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("""CREATE TABLE IF NOT EXISTS policies(
entity_id TEXT PRIMARY KEY, approvers_json TEXT NOT NULL, threshold INTEGER NOT NULL)""")
db.execute("""CREATE TABLE IF NOT EXISTS requests(
Expand All @@ -168,22 +182,22 @@ def set_policy(self, entity_id: str, approvers: list[str], threshold: int) -> di
unique = sorted(set(approvers)); threshold = int(threshold)
if threshold < 1 or threshold > len(unique): raise ValueError("invalid recovery threshold")
for a in unique: self.identity.load_manifest(a)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("INSERT OR REPLACE INTO policies VALUES(?,?,?)",
(entity_id, json.dumps(unique), threshold))
return {"entity_id": entity_id, "approvers": unique, "threshold": threshold}

def request(self, entity_id: str, reason: Any) -> dict:
request_id = rid("recovery3")
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
if not db.execute("SELECT 1 FROM policies WHERE entity_id=?", (entity_id,)).fetchone():
raise KeyError("recovery quorum policy missing")
db.execute("INSERT INTO requests VALUES(?,?,?,?,?)",
(request_id, entity_id, digest(reason), "OPEN", now_ms()))
return {"request_id": request_id, "entity_id": entity_id, "status": "OPEN"}

def approve(self, request_id: str, approver: str) -> dict:
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
req = db.execute("SELECT * FROM requests WHERE request_id=? AND status='OPEN'",
(request_id,)).fetchone()
Expand All @@ -194,14 +208,14 @@ def approve(self, request_id: str, approver: str) -> dict:
body = {"schema": "entity-v3-recovery-approval-v1", "request_id": request_id,
"entity_id": req["entity_id"], "approver": approver, "created_at_ms": now_ms()}
sig = self.identity.sign(approver, body)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("INSERT OR REPLACE INTO approvals VALUES(?,?,?,?)",
(request_id, approver, body["created_at_ms"], json.dumps(sig, sort_keys=True)))
count = db.execute("SELECT COUNT(*) FROM approvals WHERE request_id=?", (request_id,)).fetchone()[0]
return dict(body, signature=sig, approval_count=count, threshold=int(policy["threshold"]))

def execute(self, request_id: str) -> dict:
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
req = db.execute("SELECT * FROM requests WHERE request_id=? AND status='OPEN'",
(request_id,)).fetchone()
Expand All @@ -218,7 +232,7 @@ def execute(self, request_id: str) -> dict:
if not self.identity.verify_signature(manifest, body, json.loads(row["signature_json"])):
raise PermissionError("invalid recovery approval")
result = self.identity.recover_signing_key(req["entity_id"])
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("UPDATE requests SET status='EXECUTED' WHERE request_id=?", (request_id,))
return {"request_id": request_id, "entity_id": req["entity_id"],
"status": "EXECUTED", "manifest_revision": result["manifest_revision"],
Expand Down
26 changes: 20 additions & 6 deletions src/31_Profiles/profile_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
from pathlib import Path
from typing import Any
import hashlib, json, sqlite3, time
from contextlib import contextmanager


@contextmanager
def dbctx(path):
db = sqlite3.connect(path)
try:
yield db
db.commit()
except Exception:
db.rollback()
raise
finally:
db.close()

CORE_VERSION = "3.0.0"
CORE_PRIMITIVES = ("ENTITY", "AUTHORITY", "RIGHT", "EVENT", "VALUE")
Expand Down Expand Up @@ -35,7 +49,7 @@ class ProfileRegistry:
def __init__(self, root: str | Path):
self.path = Path(root) / "entity_v3_profiles.sqlite"
self.path.parent.mkdir(parents=True, exist_ok=True)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("""CREATE TABLE IF NOT EXISTS profiles(
profile_id TEXT NOT NULL, version TEXT NOT NULL, schema_hash TEXT NOT NULL,
dependencies_json TEXT NOT NULL, mandatory INTEGER NOT NULL,
Expand All @@ -50,7 +64,7 @@ def register(self, d: ProfileDescriptor) -> dict:
if len(d.schema_hash) != 64:
raise ValueError("schema_hash must be SHA-256")
deps = tuple(sorted(set(d.dependencies)))
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
old = db.execute("SELECT * FROM profiles WHERE profile_id=? AND version=?",
(d.profile_id, d.version)).fetchone()
Expand Down Expand Up @@ -87,7 +101,7 @@ def register_schema(self, schema_id: str, version: str, document: Any,
if compatibility not in {"IMMUTABLE", "BACKWARD", "FORWARD", "BIDIRECTIONAL"}:
raise ValueError("invalid compatibility")
digest = sha256(document)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
old = db.execute("SELECT * FROM schemas WHERE schema_id=? AND version=?",
(schema_id, version)).fetchone()
Expand Down Expand Up @@ -161,7 +175,7 @@ class StandardGovernance:
def __init__(self, root: str | Path, identity):
self.path = Path(root) / "entity_v3_standard_governance.sqlite"
self.identity = identity
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("""CREATE TABLE IF NOT EXISTS rfcs(
rfc_id TEXT PRIMARY KEY, proposer TEXT NOT NULL, body_sha256 TEXT NOT NULL,
change_class TEXT NOT NULL, threshold INTEGER NOT NULL,
Expand All @@ -181,7 +195,7 @@ def propose(self, proposer: str, body: Any, change_class="PROFILE", threshold=2)
"body_sha256": digest, "change_class": change_class,
"threshold": max(1, int(threshold)), "status": "OPEN", "created_at_ms": now_ms()}
sig = self.identity.sign(proposer, record)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.execute("INSERT INTO rfcs VALUES(?,?,?,?,?,?,?,?)", (
rfc_id, proposer, digest, change_class, record["threshold"],
"OPEN", record["created_at_ms"], json.dumps(sig, sort_keys=True)))
Expand All @@ -194,7 +208,7 @@ def endorse(self, rfc_id: str, endorser: str, decision="APPROVE") -> dict:
record = {"schema": "entity-v3-rfc-endorsement-v1", "rfc_id": rfc_id,
"endorser": endorser, "decision": decision, "created_at_ms": now_ms()}
sig = self.identity.sign(endorser, record)
with sqlite3.connect(self.path) as db:
with dbctx(self.path) as db:
db.row_factory = sqlite3.Row
rfc = db.execute("SELECT * FROM rfcs WHERE rfc_id=? AND status='OPEN'", (rfc_id,)).fetchone()
if not rfc: raise KeyError("open RFC not found")
Expand Down
Loading
Loading