Settings, conventions (posting templates, approval rules, policies, close steps, calendar, mappings, notes), decisions, open items and entry approvals are journal events (journal format 2). Books that keep their settings never read wanderbooks.toml or config.json; the server and the viewer take the vault key from --vault-key-file instead. books.import_settings moves a settings file in once, exactly as the server reads it. Approval rules, when enforced, gate every posting path. Replay refuses what it can't read as newer, never as corrupt. Lean: a record changes no figure. Mutation on the whole diff: every survivor killed by a test but two equivalent (docs/testing.md). The Company page says a late open item is overdue in words, not colour alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
71 files changed
+12249
-461
No files matched your search
+1
@@ -0,0 +1 @@
|
||||
%PDF-1.4 fixture
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"assets": [],
|
||||
"bills": [],
|
||||
"entries": [
|
||||
{
|
||||
"date": "2026-10-05",
|
||||
"description": "Joint contribution",
|
||||
"id": 1,
|
||||
"lines": [
|
||||
{
|
||||
"account": 1,
|
||||
"amount": {
|
||||
"amount": "1000.01",
|
||||
"currency": [
|
||||
85,
|
||||
83,
|
||||
68
|
||||
]
|
||||
},
|
||||
"side": "Debit"
|
||||
},
|
||||
{
|
||||
"account": 3,
|
||||
"amount": {
|
||||
"amount": "500.01",
|
||||
"currency": [
|
||||
85,
|
||||
83,
|
||||
68
|
||||
]
|
||||
},
|
||||
"side": "Credit"
|
||||
},
|
||||
{
|
||||
"account": 4,
|
||||
"amount": {
|
||||
"amount": "500.00",
|
||||
"currency": [
|
||||
85,
|
||||
83,
|
||||
68
|
||||
]
|
||||
},
|
||||
"side": "Credit"
|
||||
}
|
||||
],
|
||||
"reversal_of": null,
|
||||
"status": "Draft"
|
||||
}
|
||||
],
|
||||
"entry_parties": [],
|
||||
"invoices": [],
|
||||
"payroll_runs": [],
|
||||
"periods": [],
|
||||
"recurring": [],
|
||||
"schedules": [],
|
||||
"snapshot": {
|
||||
"Ok": {
|
||||
"balance_sheet": {
|
||||
"assets": "0",
|
||||
"balanced": true,
|
||||
"current_earnings": "0",
|
||||
"equity": "0",
|
||||
"liabilities": "0"
|
||||
},
|
||||
"profit_and_loss": {
|
||||
"expenses": "0",
|
||||
"net_income": "0",
|
||||
"revenue": "0"
|
||||
},
|
||||
"trial_balance": {
|
||||
"lines": [],
|
||||
"total_credits": "0",
|
||||
"total_debits": "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"verify": {
|
||||
"Ok": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{"payload":{"base_currency":"USD"},"prev":"0000000000000000000000000000000000000000000000000000000000000000","seq":1,"ts":"2026-10-17T19:53:25Z","type":"store.created"}
|
||||
{"payload":{"account_type":"Asset","code":"1000","currency":"USD","id":1,"name":"Bank","parent":null,"placeholder":false},"prev":"d831941701fea09ffd8217f36cba5da99d1a45d0113dc50a47248dcb80280ff6","seq":2,"ts":"2026-10-17T19:53:25Z","type":"account.added"}
|
||||
{"payload":{"account_type":"Liability","code":"2100","currency":"USD","id":2,"name":"Due to Members","parent":null,"placeholder":false},"prev":"b50cde605a07e1ea7f3d2706337b3c78c89e98059e31d2a7f8dcfb4263a544e4","seq":3,"ts":"2026-10-17T19:53:25Z","type":"account.added"}
|
||||
{"payload":{"account_type":"Equity","code":"3000","currency":"USD","id":3,"name":"Capital A","parent":null,"placeholder":false},"prev":"a25661e16d53f331435bee703b2ec5025323c6f403bdf20d323209415108ac8d","seq":4,"ts":"2026-10-17T19:53:25Z","type":"account.added"}
|
||||
{"payload":{"account_type":"Equity","code":"3001","currency":"USD","id":4,"name":"Capital B","parent":null,"placeholder":false},"prev":"6cdb2d87b823654180c453e845b8352a029f9ec088950565a358edb5b1763395","seq":5,"ts":"2026-10-17T19:53:25Z","type":"account.added"}
|
||||
{"payload":{"account_type":"Expense","code":"6000","currency":"USD","id":5,"name":"Software","parent":null,"placeholder":false},"prev":"909accf560d58465cc34052bf3f0142cc6125e8ad1a04597e7c4f833dbccee4e","seq":6,"ts":"2026-10-17T19:53:25Z","type":"account.added"}
|
||||
{"payload":{"features":[],"format":2},"prev":"5784dc3749592777a990411ece951993d547579bd25249b7f4bc10a48b0e1924","seq":7,"ts":"2026-10-17T19:53:25Z","type":"journal.format_set"}
|
||||
{"payload":{"changes":[{"key":"company.name","value":"Fixture Labs LLC"},{"key":"company.tax_classification","value":"partnership"},{"key":"company.ein","value":"98-7654321"},{"key":"company.timezone","value":"America/Denver"},{"key":"policy.evidence.threshold","value":"0.00"},{"key":"books.cash_accounts","value":["1000"]},{"key":"books.financing_accounts","value":["2100"]},{"key":"policy.parties","value":"require"},{"key":"company.members","value":[{"capital_account":"3000","files_jointly_with":"B","name":"A","share":"0.5"},{"capital_account":"3001","files_jointly_with":"A","name":"B","share":"0.5"}]}],"source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17","note":"Imported from wanderbooks.toml."}},"prev":"3c4dc4a46cdb8ecf6c6dc453f1cabe68a4790a75c7ee8b5f9e300bd6599d384e","seq":8,"ts":"2026-10-17T19:53:25Z","type":"settings.set"}
|
||||
{"payload":{"body_md":"Cash in from both members, half each.","id":"joint-contribution","kind":"posting_template","source":{"decided_by":"A","decided_on":"2026-10-17"},"structured":{"lines":[{"account":"1000","share":"1","side":"debit"},{"account":"3000","share":"0.5","side":"credit"},{"account":"3001","share":"0.5","side":"credit"}]},"title":"Joint contribution"},"prev":"f8db15c21564855f32f6cee9124c1085861755ea585a4516803eca7d6b8d77bf","seq":9,"ts":"2026-10-17T19:53:25Z","type":"convention.set"}
|
||||
{"payload":{"body_md":"Cash in from both members, half each; one entry per member when they pay separately.","id":"joint-contribution","kind":"posting_template","source":{"decided_by":"A","decided_on":"2026-10-17"},"structured":{"lines":[{"account":"1000","share":"1","side":"debit"},{"account":"3000","share":"0.5","side":"credit"},{"account":"3001","share":"0.5","side":"credit"}]},"title":"Joint contribution"},"prev":"60d268b71739270907396ba0d43c6dd0af3333059148e6779b91f33454c31e3f","seq":10,"ts":"2026-10-17T19:53:25Z","type":"convention.set"}
|
||||
{"payload":{"body_md":"Software over 500 needs B.","id":"over-500","kind":"approval_rule","source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"},"structured":{"accounts":["6000"],"amount_over":"500","approver":"B"},"title":"Big spends"},"prev":"fa42802688f2f805b89c9c12cab7b605161372366f703ec26dcbe0bcec3546f6","seq":11,"ts":"2026-10-17T19:53:25Z","type":"convention.set"}
|
||||
{"payload":{"body_md":"Ask whether a member paid anything personally.","id":"close-ask","kind":"close_step","source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"},"title":"Ask about personal cards"},"prev":"1aa1e62869b877ab5dbc8a958e8cffbc06c2e3b718544b445ed32a260f42296b","seq":12,"ts":"2026-10-17T19:53:25Z","type":"convention.set"}
|
||||
{"payload":{"id":"close-ask","reason":"Folded into the checklist.","source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"}},"prev":"493312949ca1ec854bd2911a0b75d1aaf8831650c61184361c8310201c82469b","seq":13,"ts":"2026-10-17T19:53:25Z","type":"convention.retired"}
|
||||
{"payload":{"attachment_id":1,"blob_sha":"c5c2e8be6ad0825a56ded1f1a153ceaf11dc060ab44b120a94406a08207babc2","category":"legal","description":null,"entry_id":null,"file_name":"oa.pdf","mime_type":"application/pdf","size_bytes":16},"prev":"d9cf1fdee068162629a888391b8fb711b19121dc77cb931803ea05611511c760","seq":14,"ts":"2026-10-17T19:53:25Z","type":"document.filed"}
|
||||
{"payload":{"citation":"Treas. Reg. 1.263(a)-1(f)","decided_by":["Stephen Waits","B"],"decided_on":"2026-10-11","decision_md":"Expense tangible items up to 2,500.","evidence_attachment":1,"id":1,"subject":"Materiality"},"prev":"d50543fad98a8a4bee7be0d01d94e9c44d26193fb2e83797891f99e9ee8b29cd","seq":15,"ts":"2026-10-17T19:53:25Z","type":"decision.recorded"}
|
||||
{"payload":{"decided_by":["Stephen Waits"],"decided_on":"2026-10-16","decision_md":"Corrected: prepaid services follow the 12-month rule.","id":2,"subject":"Materiality","supersedes":1},"prev":"1c59d193f4686dbaa0436b27290965d19b75dfaf288bc315644a39e052908f09","seq":16,"ts":"2026-10-17T19:53:25Z","type":"decision.recorded"}
|
||||
{"payload":{"detail_md":"Signed; mailing pending.","due":"2026-10-24","id":1,"source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"},"title":"Mail the letter"},"prev":"4a6290f4a8edb803dd96829c0e6e2b23c36e4c93cb61d94d54c170d09080b78a","seq":17,"ts":"2026-10-17T19:53:25Z","type":"open_item.raised"}
|
||||
{"payload":{"id":2,"source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"},"title":"Ask the CPA"},"prev":"2e3ef6a21257e4313bbf65e665dafe9a8d80c1aa6539871d5eef1a996efa7988","seq":18,"ts":"2026-10-17T19:53:25Z","type":"open_item.raised"}
|
||||
{"payload":{"id":2,"resolution":"Asked.","source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"}},"prev":"4c372f8f1b3cd65c03034111795a484a575f10c6915c4e8d8fe0168680b9f331","seq":19,"ts":"2026-10-17T19:53:25Z","type":"open_item.resolved"}
|
||||
{"payload":{"date":"2026-10-05","description":"Joint contribution","id":1},"prev":"45654a1f4da8a087ae0fb0659948b24083d11c1d7462fa254f611028b5d99635","seq":20,"ts":"2026-10-17T19:53:25Z","type":"entry.created"}
|
||||
{"payload":{"account":1,"amount":"1000.01","currency":"USD","id":1,"side":"debit"},"prev":"177a36f401e11b3245f2e2a2461dd2d5032828a8cd7697413a7db9a681f65431","seq":21,"ts":"2026-10-17T19:53:25Z","type":"entry.line_added"}
|
||||
{"payload":{"account":3,"amount":"500.01","currency":"USD","id":1,"side":"credit"},"prev":"41a32391ae41eba2935ff0cecd69da86c85a442425ddca614ce826f8ddc20fcc","seq":22,"ts":"2026-10-17T19:53:25Z","type":"entry.line_added"}
|
||||
{"payload":{"account":4,"amount":"500.00","currency":"USD","id":1,"side":"credit"},"prev":"273758a9fed94fd458248d1edc6380dd3e3af95a7cd6b4eeb94e0d7809855a63","seq":23,"ts":"2026-10-17T19:53:25Z","type":"entry.line_added"}
|
||||
{"payload":{"approver":"B","entry_id":1,"fingerprint":"807a5fdd769adedb","note":"ok","source":{"decided_by":"B","decided_on":"2026-10-17"}},"prev":"adeb163a99746991b5fb6e38423a5b5ee85ced58142d4baae8c9fa4760124b92","seq":24,"ts":"2026-10-17T19:53:25Z","type":"entry.approved"}
|
||||
{"payload":{"changes":[{"key":"policy.approval_rules","value":"enforce"},{"key":"company.timezone","value":null}],"source":{"decided_by":"Stephen Waits","decided_on":"2026-10-17"}},"prev":"a32a3b4605afc252393a76fa18f4db2321ac4bda475599a0003c75bf2da82696","seq":25,"ts":"2026-10-17T19:53:25Z","type":"settings.set"}
|
||||
@@ -0,0 +1,289 @@
|
||||
{
|
||||
"approvals": [
|
||||
{
|
||||
"approver": "B",
|
||||
"entry": 1,
|
||||
"fingerprint": "807a5fdd769adedb",
|
||||
"note": "ok",
|
||||
"seq": 24,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "B",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"conventions": [
|
||||
{
|
||||
"body_md": "Ask whether a member paid anything personally.",
|
||||
"id": "close-ask",
|
||||
"kind": "close_step",
|
||||
"retired": {
|
||||
"seq": 13,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"text": "Folded into the checklist."
|
||||
},
|
||||
"revision": 1,
|
||||
"seq": 12,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"structured": null,
|
||||
"title": "Ask about personal cards"
|
||||
},
|
||||
{
|
||||
"body_md": "Cash in from both members, half each; one entry per member when they pay separately.",
|
||||
"id": "joint-contribution",
|
||||
"kind": "posting_template",
|
||||
"retired": null,
|
||||
"revision": 2,
|
||||
"seq": 10,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "A",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"structured": {
|
||||
"lines": [
|
||||
{
|
||||
"account": "1000",
|
||||
"share": "1",
|
||||
"side": "debit"
|
||||
},
|
||||
{
|
||||
"account": "3000",
|
||||
"share": "0.5",
|
||||
"side": "credit"
|
||||
},
|
||||
{
|
||||
"account": "3001",
|
||||
"share": "0.5",
|
||||
"side": "credit"
|
||||
}
|
||||
]
|
||||
},
|
||||
"title": "Joint contribution"
|
||||
},
|
||||
{
|
||||
"body_md": "Software over 500 needs B.",
|
||||
"id": "over-500",
|
||||
"kind": "approval_rule",
|
||||
"retired": null,
|
||||
"revision": 1,
|
||||
"seq": 11,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"structured": {
|
||||
"accounts": [
|
||||
"6000"
|
||||
],
|
||||
"amount_over": "500",
|
||||
"approver": "B"
|
||||
},
|
||||
"title": "Big spends"
|
||||
}
|
||||
],
|
||||
"decisions": [
|
||||
{
|
||||
"citation": "Treas. Reg. 1.263(a)-1(f)",
|
||||
"decided_by": [
|
||||
"Stephen Waits",
|
||||
"B"
|
||||
],
|
||||
"decided_on": "2026-10-11",
|
||||
"decision_md": "Expense tangible items up to 2,500.",
|
||||
"evidence_attachment": 1,
|
||||
"id": 1,
|
||||
"seq": 15,
|
||||
"subject": "Materiality",
|
||||
"superseded_by": 2,
|
||||
"supersedes": null
|
||||
},
|
||||
{
|
||||
"citation": null,
|
||||
"decided_by": [
|
||||
"Stephen Waits"
|
||||
],
|
||||
"decided_on": "2026-10-16",
|
||||
"decision_md": "Corrected: prepaid services follow the 12-month rule.",
|
||||
"evidence_attachment": null,
|
||||
"id": 2,
|
||||
"seq": 16,
|
||||
"subject": "Materiality",
|
||||
"superseded_by": null,
|
||||
"supersedes": 1
|
||||
}
|
||||
],
|
||||
"open_items": [
|
||||
{
|
||||
"detail_md": "Signed; mailing pending.",
|
||||
"due": "2026-10-24",
|
||||
"id": 1,
|
||||
"resolved": null,
|
||||
"seq": 17,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"title": "Mail the letter"
|
||||
},
|
||||
{
|
||||
"detail_md": null,
|
||||
"due": null,
|
||||
"id": 2,
|
||||
"resolved": {
|
||||
"seq": 19,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"text": "Asked."
|
||||
},
|
||||
"seq": 18,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"title": "Ask the CPA"
|
||||
}
|
||||
],
|
||||
"settings": [
|
||||
{
|
||||
"key": "company.name",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": "Fixture Labs LLC"
|
||||
},
|
||||
{
|
||||
"key": "company.tax_classification",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": "partnership"
|
||||
},
|
||||
{
|
||||
"key": "company.ein",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": "98-7654321"
|
||||
},
|
||||
{
|
||||
"key": "company.members",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": [
|
||||
{
|
||||
"capital_account": "3000",
|
||||
"files_jointly_with": "B",
|
||||
"name": "A",
|
||||
"share": "0.5"
|
||||
},
|
||||
{
|
||||
"capital_account": "3001",
|
||||
"files_jointly_with": "A",
|
||||
"name": "B",
|
||||
"share": "0.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "books.cash_accounts",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": [
|
||||
"1000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "books.financing_accounts",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": [
|
||||
"2100"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "policy.evidence.threshold",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": "0.00"
|
||||
},
|
||||
{
|
||||
"key": "policy.parties",
|
||||
"seq": 8,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": "Imported from wanderbooks.toml."
|
||||
},
|
||||
"value": "require"
|
||||
},
|
||||
{
|
||||
"key": "policy.approval_rules",
|
||||
"seq": 25,
|
||||
"source": {
|
||||
"citation": null,
|
||||
"decided_by": "Stephen Waits",
|
||||
"decided_on": "2026-10-17",
|
||||
"note": null
|
||||
},
|
||||
"value": "enforce"
|
||||
}
|
||||
],
|
||||
"settings_last_seq": 25
|
||||
}
|
||||
@@ -118,21 +118,21 @@ fn assert_corrupt<T>(got: Result<T, StoreError>) {
|
||||
|
||||
/// Oracle (plan/served.md 5.1): an older reader meets books a newer
|
||||
/// wanderbooks wrote. A valid line of an unknown type, and a declared
|
||||
/// format 2, are each NewerJournal, from the writer and the viewer alike,
|
||||
/// format 3, are each NewerJournal, from the writer and the viewer alike,
|
||||
/// and the refusal reads nothing further: the database isn't rebuilt and
|
||||
/// the journal is untouched.
|
||||
#[test]
|
||||
fn old_reader_gets_newer_journal() {
|
||||
let cases = [
|
||||
(
|
||||
"settings.set",
|
||||
"period.attested",
|
||||
json!({"key": "company.name", "value": "X"}),
|
||||
"an event type this version doesn't know",
|
||||
),
|
||||
(
|
||||
FORMAT_SET,
|
||||
json!({"format": 2, "features": []}),
|
||||
"journal format 2",
|
||||
json!({"format": 3, "features": []}),
|
||||
"journal format 3",
|
||||
),
|
||||
(
|
||||
FORMAT_SET,
|
||||
@@ -218,12 +218,12 @@ fn the_writer_and_the_viewer_agree_on_newer_books() {
|
||||
&[
|
||||
// Chained and of a known type, but replay refuses it.
|
||||
("entry.posted", json!({"id": 99})),
|
||||
("settings.set", json!({"key": "company.name"})),
|
||||
("period.attested", json!({"key": "company.name"})),
|
||||
],
|
||||
)[1];
|
||||
let need = "an event type this version doesn't know";
|
||||
assert_newer(Store::open(&dir), seq, "settings.set", need, false);
|
||||
assert_newer(Snapshot::load(&dir), seq, "settings.set", need, false);
|
||||
assert_newer(Store::open(&dir), seq, "period.attested", need, false);
|
||||
assert_newer(Snapshot::load(&dir), seq, "period.attested", need, false);
|
||||
}
|
||||
|
||||
/// Damage stays corruption, whatever the damaged line's type: the gate
|
||||
@@ -256,8 +256,8 @@ fn damaged_journals_are_still_corrupt() {
|
||||
}),
|
||||
];
|
||||
let newer = [
|
||||
(FORMAT_SET, json!({"format": 2, "features": []})),
|
||||
("settings.set", json!({"key": "company.name"})),
|
||||
(FORMAT_SET, json!({"format": 3, "features": []})),
|
||||
("period.attested", json!({"key": "company.name"})),
|
||||
];
|
||||
for (name, damage) in damages {
|
||||
for (i, last) in newer.iter().enumerate() {
|
||||
@@ -541,32 +541,32 @@ fn a_newer_format_frames_its_lines_its_own_way() {
|
||||
let nexts: [(&str, Next, Option<bool>); 6] = [
|
||||
(
|
||||
"float",
|
||||
|seq, prev| json!({"seq": seq, "ts": "t", "type": "settings.set", "payload": {"rate": 0.5}, "prev": prev}),
|
||||
|seq, prev| json!({"seq": seq, "ts": "t", "type": "period.attested", "payload": {"rate": 0.5}, "prev": prev}),
|
||||
Some(true),
|
||||
),
|
||||
(
|
||||
"string-seq",
|
||||
|seq, prev| json!({"seq": seq.to_string(), "ts": "t", "type": "settings.set", "payload": {}, "prev": prev}),
|
||||
|seq, prev| json!({"seq": seq.to_string(), "ts": "t", "type": "period.attested", "payload": {}, "prev": prev}),
|
||||
Some(true),
|
||||
),
|
||||
(
|
||||
"envelope-key",
|
||||
|seq, prev| json!({"seq": seq, "ts": "t", "type": "settings.set", "payload": {}, "prev": prev, "actor": "agent"}),
|
||||
|seq, prev| json!({"seq": seq, "ts": "t", "type": "period.attested", "payload": {}, "prev": prev, "actor": "agent"}),
|
||||
Some(true),
|
||||
),
|
||||
(
|
||||
"no-prev",
|
||||
|seq, prev| json!({"seq": seq, "ts": "t", "type": "settings.set", "payload": {}, "parent": prev}),
|
||||
|seq, prev| json!({"seq": seq, "ts": "t", "type": "period.attested", "payload": {}, "parent": prev}),
|
||||
Some(false),
|
||||
),
|
||||
(
|
||||
"prev-not-text",
|
||||
|seq, _| json!({"seq": seq, "ts": "t", "type": "settings.set", "payload": {}, "prev": 1.5}),
|
||||
|seq, _| json!({"seq": seq, "ts": "t", "type": "period.attested", "payload": {}, "prev": 1.5}),
|
||||
Some(false),
|
||||
),
|
||||
(
|
||||
"wrong-prev",
|
||||
|seq, _| json!({"seq": seq, "ts": "t", "type": "settings.set", "payload": {"rate": 0.5}, "prev": "00"}),
|
||||
|seq, _| json!({"seq": seq, "ts": "t", "type": "period.attested", "payload": {"rate": 0.5}, "prev": "00"}),
|
||||
None,
|
||||
),
|
||||
];
|
||||
@@ -575,7 +575,7 @@ fn a_newer_format_frames_its_lines_its_own_way() {
|
||||
books(&dir);
|
||||
let seq = append(
|
||||
&dir,
|
||||
&[(FORMAT_SET, json!({"format": 2, "features": ["actors"]}))],
|
||||
&[(FORMAT_SET, json!({"format": 3, "features": ["actors"]}))],
|
||||
)[0];
|
||||
let (_, hash) = last_line(&dir);
|
||||
append_raw(
|
||||
@@ -584,8 +584,8 @@ fn a_newer_format_frames_its_lines_its_own_way() {
|
||||
);
|
||||
match verified {
|
||||
Some(v) => {
|
||||
assert_newer(Store::open(&dir), seq, FORMAT_SET, "journal format 2", v);
|
||||
assert_newer(Snapshot::load(&dir), seq, FORMAT_SET, "journal format 2", v);
|
||||
assert_newer(Store::open(&dir), seq, FORMAT_SET, "journal format 3", v);
|
||||
assert_newer(Snapshot::load(&dir), seq, FORMAT_SET, "journal format 3", v);
|
||||
}
|
||||
None => {
|
||||
assert_corrupt(Store::open(&dir));
|
||||
@@ -661,11 +661,11 @@ fn a_line_that_is_not_utf8_is_corrupt_for_the_viewer_and_the_writer() {
|
||||
} else {
|
||||
// After a refused line, it is a next line without a readable
|
||||
// prev: unverified, for both.
|
||||
let seq = append(&dir, &[("settings.set", json!({}))])[0];
|
||||
let seq = append(&dir, &[("period.attested", json!({}))])[0];
|
||||
append_raw(&dir, b"{\"prev\":\"\xff\"}\n");
|
||||
let need = "an event type this version doesn't know";
|
||||
assert_newer(Store::open(&dir), seq, "settings.set", need, false);
|
||||
assert_newer(Snapshot::load(&dir), seq, "settings.set", need, false);
|
||||
assert_newer(Store::open(&dir), seq, "period.attested", need, false);
|
||||
assert_newer(Snapshot::load(&dir), seq, "period.attested", need, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -678,12 +678,12 @@ fn a_line_that_is_not_utf8_is_corrupt_for_the_viewer_and_the_writer() {
|
||||
fn an_old_reader_never_repairs_newer_books() {
|
||||
let dir = test_dir("newer-torn");
|
||||
books(&dir);
|
||||
let seq = append(&dir, &[("settings.set", json!({"key": "company.name"}))])[0];
|
||||
let seq = append(&dir, &[("period.attested", json!({"key": "company.name"}))])[0];
|
||||
append_raw(&dir, b"{\"seq\":");
|
||||
let path = dir.join(JOURNAL_FILE);
|
||||
let before = std::fs::read(&path).unwrap();
|
||||
let need = "an event type this version doesn't know";
|
||||
assert_newer(Store::open(&dir), seq, "settings.set", need, false);
|
||||
assert_newer(Store::open(&dir), seq, "period.attested", need, false);
|
||||
assert_eq!(std::fs::read(&path).unwrap(), before);
|
||||
let set_aside: Vec<_> = std::fs::read_dir(&dir)
|
||||
.unwrap()
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user