Describe the bug
@flatbread/proof@1.0.1 validates that create-time relation targets exist, but
it does not apply the same Effort boundary used by later lifecycle mutations.
Three create forms commit cross-Effort edges:
derives_from on WriteDecision;
supersedes on WriteFinding;
invalidates on WriteDecision.
The equivalent later Supersede and Invalidate mutations reject the edge.
Cross-Effort ResolveIssue, SetRiskState.evidence, and cites also reject.
An effort-scoped proof relations read then drops the committed foreign
derives_from target and reports 0 records; complete. The snapshot still
contains the edge, and create-time supersedes and invalidates also write
reverse projections into the foreign target.
This lets one mutation commit data that the read contract hides and the later
mutation contract rejects.
Reproduction
Using exact @flatbread/proof@1.0.1 and flatbread@1.0.1:
- Create Efforts A and B.
- Create Finding A in Effort A and Finding B in Effort B.
- Run these writes:
{
"type": "WriteDecision",
"effort": "<effort-b>",
"title": "Cross derives-from",
"body": "Must stay inside Effort B.",
"derives_from": ["<finding-a>"]
}
{
"type": "WriteFinding",
"effort": "<effort-b>",
"title": "Cross supersedes",
"body": "Must stay inside Effort B.",
"kind": "measurement",
"supersedes": ["<finding-a>"]
}
{
"type": "WriteDecision",
"effort": "<effort-b>",
"title": "Cross invalidates",
"body": "Must stay inside Effort B.",
"invalidates": ["<finding-a>"]
}
All three exit 0 and advance the durable generation. A strict read of the first
edge then exits 0 with no record:
flatbread proof relations <effort-b> <decision-id> \
--relations derives_from \
--strict-min-generation <write-generation>
Observed envelope fields:
{
"summary": "0 records; complete",
"page": { "returned": 0, "has_more": false, "next_cursor": null }
}
buildProofSnapshot(root).getRecord(decisionId).frontmatter.derives_from
still contains Finding A.
Expected behavior
- Every create-time
derives_from, supersedes, and invalidates target must
belong to the source record's Effort. The Effort record itself may count as
belonging to that Effort if such links are supported.
- A rejected write must create no record, write no reverse edge, and leave the
durable generation unchanged.
- Same-Effort create-time and later relation forms must keep working.
- Legacy or hand-edited foreign edges must fail with an explicit structured
integrity error. They must not become a successful empty relation page.
- Regression tests must cover all three create fields, their later mutation
forms, reverse projections, same-Effort links, and strict relation recall.
Published package identity
@flatbread/proof@1.0.1
- integrity:
sha512-khANh86EXyZ0bPPOkUzGU0VRAPOpv+5h4vGKjpuFwLdfI/Eihxk63+YHbIxtFp08gffahxgViz/SlyFPJ1LR/A==
- SHA-1:
ec969767685bec108c04d78a4dcf4e7e1ad2cf78
flatbread@1.0.1
- integrity:
sha512-WNqK93IlIRBKq6IeyAZjEqVMDcsKVBi0v3yihU+JVXSYHJMQGX7i6wt0L53RQZJ06BPxFJNG9k4yiyBGdkuIgA==
The executable Harnessflow Gate-0 fixture checks every path above without
pre-validating relations or creating collection directories.
Describe the bug
@flatbread/proof@1.0.1validates that create-time relation targets exist, butit does not apply the same Effort boundary used by later lifecycle mutations.
Three create forms commit cross-Effort edges:
derives_fromonWriteDecision;supersedesonWriteFinding;invalidatesonWriteDecision.The equivalent later
SupersedeandInvalidatemutations reject the edge.Cross-Effort
ResolveIssue,SetRiskState.evidence, andcitesalso reject.An effort-scoped
proof relationsread then drops the committed foreignderives_fromtarget and reports0 records; complete. The snapshot stillcontains the edge, and create-time
supersedesandinvalidatesalso writereverse projections into the foreign target.
This lets one mutation commit data that the read contract hides and the later
mutation contract rejects.
Reproduction
Using exact
@flatbread/proof@1.0.1andflatbread@1.0.1:{ "type": "WriteDecision", "effort": "<effort-b>", "title": "Cross derives-from", "body": "Must stay inside Effort B.", "derives_from": ["<finding-a>"] }{ "type": "WriteFinding", "effort": "<effort-b>", "title": "Cross supersedes", "body": "Must stay inside Effort B.", "kind": "measurement", "supersedes": ["<finding-a>"] }{ "type": "WriteDecision", "effort": "<effort-b>", "title": "Cross invalidates", "body": "Must stay inside Effort B.", "invalidates": ["<finding-a>"] }All three exit 0 and advance the durable generation. A strict read of the first
edge then exits 0 with no record:
Observed envelope fields:
{ "summary": "0 records; complete", "page": { "returned": 0, "has_more": false, "next_cursor": null } }buildProofSnapshot(root).getRecord(decisionId).frontmatter.derives_fromstill contains Finding A.
Expected behavior
derives_from,supersedes, andinvalidatestarget mustbelong to the source record's Effort. The Effort record itself may count as
belonging to that Effort if such links are supported.
durable generation unchanged.
integrity error. They must not become a successful empty relation page.
forms, reverse projections, same-Effort links, and strict relation recall.
Published package identity
@flatbread/proof@1.0.1sha512-khANh86EXyZ0bPPOkUzGU0VRAPOpv+5h4vGKjpuFwLdfI/Eihxk63+YHbIxtFp08gffahxgViz/SlyFPJ1LR/A==ec969767685bec108c04d78a4dcf4e7e1ad2cf78flatbread@1.0.1sha512-WNqK93IlIRBKq6IeyAZjEqVMDcsKVBi0v3yihU+JVXSYHJMQGX7i6wt0L53RQZJ06BPxFJNG9k4yiyBGdkuIgA==The executable Harnessflow Gate-0 fixture checks every path above without
pre-validating relations or creating collection directories.