Repository navigation
Conversation
… table A frame with audit_read attribution excused any log entry the bot wrote for a declared record, whatever table it wrote (#1505): an insurance row, an allergy or a note for the new patient verified. audit_read now needs scope_field and writes: which entry field says what was written (with scope_encoding and scope_pattern for OpenEMR's base64-encoded statements) and the tables the save writes. A bot entry for a declared record in any other table, or one that names no table, is collateral; evidence.frame.collateral_scopes names them. On the independent suite's OpenEMR stand-in (the pinned fixture's own dump), framed goes from 3 to 2 missed faults of 15 with no new false alarms: benchmark/frame_scope_1505/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
abrichr
left a comment
There was a problem hiding this comment.
Coordinator safety review (AI-assisted). Approved, with small fixes.
- Reserve
unknownin the validator: listing it inwriteswould excuse every unscoped bot entry. - Check the SQL verb. Add an optional verb allow-list in
writes(for exampleops: [insert]). Today a DELETE or UPDATE on a listed table is excused. - Document in VERIFY_RUN.md that
writesis set by the frame's author, not derived from the declared effects. - Rename the
history_deletetest case, which logs a DELETE oninsurance_data.
Review of #1536: - writes entries take an optional ops list ({table, ops: [insert]}), read from scope_pattern's op group, so a DELETE or UPDATE on a table the save only inserts into is collateral (history_data:delete). - "unknown", the scope of an entry that names no table, can't be declared. - VERIFY_RUN.md says writes is author-set, not derived from the effects. - The delete test case is named for the table it writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
AI re-review (coordinator). All four items fixed in a3f9373. (1) |
# Conflicts: # llms-full.txt
…ed set The lint job refused the two unregistered result files. mypy flagged stray, reused for a list of fields and a set of scopes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Superseded by #1860, which closes #1505 on main's redesigned attribution: an audit_read frame without frame.database never holds, and the whole-database diff (#1582) judges the bot's other writes for the saved record as rows. This PR's narrower fix, excusing bot entries only for declared tables (scope_field, writes), would have had to be rebuilt on main's record_key/table_field design. The evidence in benchmark/frame_scope_1505 stays on this branch; keeping it. |
Pull request was closed
Closes #1505.
A frame with
audit_readattribution excused any log entry the bot wrote for the saved patient, in any table. An extra insurance row, an allergy or a note for the new patient came outverified.Change
audit_readattribution now needs two more keys:scope_field: the log-entry field that says what was written. For OpenEMR it iscomments, which holds the statement base64-encoded, read withscope_encoding: base64and ascope_patternregex.writes: the tables the save writes for a declared record, for the New Patient save[patient_data, history_data]. The frame's author declares it; it is not derived from the effects. An entry can narrow a table to verbs,{table: history_data, ops: [insert]}, read from the pattern'sopgroup, so aDELETEorUPDATEthere is collateral.unknownis reserved for an entry that names no table.A bot entry for a declared record in any other table is collateral. So is a bot entry whose table can't be read (an empty or unreadable statement). The outcome is
reconciliation_required, andevidence.frame.collateral_scopesnames the tables. Another user's entries are handled as before. Anaudit_readframe withoutscope_fieldandwritesno longer loads; no shipped contract declares one.This changes when VERIFIED is issued: it is issued less often, never more.
Tests
tests/test_frame_conditions.py: an OpenEMR-shaped SQLite store with OpenEMR's column names and its base64 statement format, throughverify-run:ops: [insert], aDELETEonhistory_datais refused;writes: [unknown]andopswithout anopgroup are refused;benchmark/frame_scope_1505/): the independent suite's 17 cases on its stand-in, the SQLite copy of the pinned OpenEMR fixture's own dump.framed, faults missedframed, false alarmsThe case that changed is
unrelated_table_insurance_new_patient. The two misses left are #1507 (wrong provider) and #1508 (missinghistory_datarow).pytest tests/test_frame_conditions.py tests/test_verify_run.py tests/test_verify_run_collateral_change.py tests/test_countersign.py: 152 passed after the review fixes (44 intest_frame_conditions.py).Limits
patient_id0 (OpenEMR audit log names no user or patient for API writes: frame attribution can't excuse or see anything #1523), so the audit log names none of them; this fix covers what the log does name.writesis per table. Fields are compared one by one only for the records the frame reads.🤖 Generated with Claude Code