Complete intake delivery wiring and narrow remaining owner blockers
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a1029c-c003-7283-acc9-930b434e6cae
This commit is contained in:
parent
49f8eb4c4b
commit
ff59199c3b
13 changed files with 452 additions and 60 deletions
|
|
@ -495,11 +495,56 @@ class Store:
|
|||
with self._connection() as db:
|
||||
return [dict(r) for r in db.execute("SELECT * FROM outbox ORDER BY rowid")]
|
||||
|
||||
def queue_heartbeats(self, now=None):
|
||||
def stage_intake_audit(self):
|
||||
"""Promote retained posed envelopes into the ordinary immutable audit outbox.
|
||||
|
||||
Same ids preserve receiver deduplication, including a previously sent
|
||||
integration job. Delivery receipts and reconciliation now use one path.
|
||||
"""
|
||||
with self._transaction() as db:
|
||||
for row in db.execute("SELECT i.id,i.payload FROM intake_deliveries i LEFT JOIN evidence e ON e.id=i.id "
|
||||
"WHERE i.kind='memo-posed' AND (e.id IS NULL OR e.envelope!=i.payload) "
|
||||
"ORDER BY i.rowid LIMIT 100").fetchall():
|
||||
event = json.loads(row['payload'])
|
||||
fields = {'id', 'type', 'source', 'subject', 'tenant', 'correlation_id', 'occurred_at', 'data'}
|
||||
data_fields = {'memo_id', 'approval_id', 'approval_binding_digest', 'submitter', 'memo_class', 'submission_digest'}
|
||||
if (set(event) != fields or not isinstance(event.get('data'), dict)
|
||||
or set(event['data']) != data_fields
|
||||
or any(not isinstance(v, str) or not v for v in event['data'].values())
|
||||
or event.get('id') != row['id'] or event.get('type') != EventClass.MEMO_POSED.value
|
||||
or event.get('source') != 'informed-decision' or event.get('tenant') != 'tenant:platform'):
|
||||
raise Conflict('invalid retained posed event')
|
||||
occurred = datetime.fromisoformat(event['occurred_at'])
|
||||
if occurred.tzinfo is None:
|
||||
raise Conflict('invalid retained posed time')
|
||||
stamp = occurred.astimezone(timezone.utc).isoformat(timespec='microseconds')
|
||||
existing = db.execute('SELECT envelope FROM evidence WHERE id=?', (row['id'],)).fetchone()
|
||||
if existing and existing[0] != row['payload']:
|
||||
raise Conflict('posed event id collision')
|
||||
db.execute('INSERT OR IGNORE INTO evidence VALUES (?,?,?,?,?)',
|
||||
(row['id'], EventClass.MEMO_POSED.value, stamp, row['payload'], row['payload']))
|
||||
db.execute('INSERT OR IGNORE INTO outbox(id) VALUES (?)', (row['id'],))
|
||||
|
||||
def settle_intake_audit(self):
|
||||
with self._transaction() as db:
|
||||
result = db.execute("UPDATE intake_deliveries SET state='delivered',lease=NULL,lease_until=NULL "
|
||||
"WHERE kind='memo-posed' AND state!='delivered' AND id IN "
|
||||
"(SELECT id FROM outbox WHERE state='delivered')")
|
||||
return result.rowcount
|
||||
|
||||
def intake_audit_pending(self):
|
||||
with self._connection() as db:
|
||||
return db.execute("SELECT 1 FROM intake_deliveries WHERE kind='memo-posed' "
|
||||
"AND state!='delivered' LIMIT 1").fetchone() is not None
|
||||
|
||||
def queue_heartbeats(self, now=None, *, include_posed=False):
|
||||
now = time.time() if now is None else now
|
||||
count = 0
|
||||
with self._transaction() as db:
|
||||
for event_class, interval in HEARTBEAT_CLASSES.items():
|
||||
classes = {**HEARTBEAT_CLASSES}
|
||||
if include_posed:
|
||||
classes[EventClass.MEMO_POSED.value] = 86400
|
||||
for event_class, interval in classes.items():
|
||||
if db.execute("SELECT 1 FROM outbox o JOIN evidence e ON e.id=o.id WHERE o.state!='delivered' "
|
||||
"AND (e.class=? OR (e.class=? AND json_extract(e.envelope,'$.data.class')=?)) LIMIT 1",
|
||||
(event_class, EventClass.HEARTBEAT.value, event_class)).fetchone():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue