@mulmoclaude/accounting-plugin 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,14 @@ export declare const optionalRecord: (value: unknown) => Record<string, unknown>
5
5
  * returned object is one this function actually proved. A half-formed
6
6
  * `{ kind: "month" }` reads as absent and the caller raises its own
7
7
  * "period is required" — previously it reached the report builders and
8
- * produced an `undefined-01` date. */
8
+ * produced an `undefined-01` date.
9
+ *
10
+ * The FORMAT is checked here too, not just the type: `typeof === "string"`
11
+ * let `{ kind: "month", period: "banana" }` through, which came back as a
12
+ * balance sheet dated `"banana-NaN"` and made the snapshot cache write
13
+ * `banana.json` / `0NaN-NaN.json` into the book (#2765). Malformed reads as
14
+ * absent so it lands on the caller's existing 400, which already spells out
15
+ * both accepted shapes for the LLM to repair its payload from. */
9
16
  export declare const optionalReportPeriod: (value: unknown) => ReportPeriod | undefined;
10
17
  /** The two fields the addEntries narration quotes back, read out of a
11
18
  * service payload that is only `unknown` to the router. */
@@ -1 +1 @@
1
- {"version":3,"file":"bodyFields.d.ts","sourceRoot":"","sources":["../../src/server/bodyFields.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAA4D,CAAC;AAEtH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAkD,CAAC;AAE7H;;;;uCAIuC;AACvC,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,YAAY,GAAG,SAOpE,CAAC;AAEF;4DAC4D;AAC5D,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAG1E,CAAC"}
1
+ {"version":3,"file":"bodyFields.d.ts","sourceRoot":"","sources":["../../src/server/bodyFields.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAA4D,CAAC;AAEtH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAkD,CAAC;AAe7H;;;;;;;;;;;mEAWmE;AACnE,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,YAAY,GAAG,SAepE,CAAC;AAEF;4DAC4D;AAC5D,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAG1E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/server/io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../src/server/io.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAe,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAsB7E,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpD;AAQD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAGvE;AAkED,wBAAsB,UAAU,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAIzF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjG;AAID,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAG7F;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9G;AAID;iEACiE;AACjE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED;;;;;;;;;;;;;kBAakB;AAClB,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9G;AAaD;;;;;;;;;6DAS6D;AAC7D,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAShI;AAcD;;4DAE4D;AAC5D,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAepJ;AAED;;qBAEqB;AACrB,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAYlG;AAID,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAExH;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASlH;AAED;;eAEe;AACf,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAoBxI;AAED;;4CAE4C;AAC5C,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAEnH;AAID,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEzF;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzF;AAED;qDACqD;AACrD,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF"}
@@ -1 +1 @@
1
- {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/server/journal.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAS7E;;;;;wDAKwD;AACxD,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;wBAEwB;AACxB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAY3G;;;;;;yDAMyD;AACzD,wBAAgB,eAAe,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAK9D;AAED;;;;;yDAKyD;AACzD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKzD;AAED;sEACsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAOhE;AA4CD;;;;mEAImE;AACnE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,WAAW,GAAG,IAAI,CAOzG;AAwBD;;;;;qDAKqD;AACrD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,iBAAiB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAMxI;AAqBD;;;;;sEAKsE;AACtE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAapE;AAgBD;;;;4CAI4C;AAC5C,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,gBAAgB,CAiBvF;AAED;;;;qBAIqB;AACrB,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,YAAY,CAWf;AAcD;;;6DAG6D;AAC7D,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIjF;AAED;;;;;;0BAM0B;AAC1B,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAoCnJ;AAED;;;;2CAI2C;AAC3C,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAMzE"}
1
+ {"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/server/journal.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAS7E;;;;;wDAKwD;AACxD,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;wBAEwB;AACxB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAY3G;;;;;;yDAMyD;AACzD,wBAAgB,eAAe,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAK9D;AAED;;;;;yDAKyD;AACzD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMzD;AAED;sEACsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAOhE;AA4CD;;;;mEAImE;AACnE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,WAAW,GAAG,IAAI,CAOzG;AAwBD;;;;;qDAKqD;AACrD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,iBAAiB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAMxI;AAqBD;;;;;sEAKsE;AACtE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAapE;AAgBD;;;;4CAI4C;AAC5C,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,gBAAgB,CAiBvF;AAED;;;;qBAIqB;AACrB,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,YAAY,CAWf;AAcD;;;6DAG6D;AAC7D,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIjF;AAED;;;;;;0BAM0B;AAC1B,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAoCnJ;AAED;;;;2CAI2C;AAC3C,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAMzE"}
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/server/report.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAe,YAAY,EAAuB,YAAY,EAAE,MAAM,EAAa,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAI/J;;;wCAGwC;AACxC,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,EAAE,CAIlG;AAED;;;;;;;;;wDASwD;AACxD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,cAAc,EAAE,CAYpF;AAUD;;;sCAGsC;AACtC,eAAO,MAAM,6BAA6B,qBAAqB,CAAC;AAgBhE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CA4B1I;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CA2B/I;AAkDD,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAgB7H"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/server/report.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAe,YAAY,EAAuB,YAAY,EAAE,MAAM,EAAa,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAI/J;;;wCAGwC;AACxC,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,EAAE,CAIlG;AAED;;;;;;;;;wDASwD;AACxD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,cAAc,EAAE,CAYpF;AAUD;;;sCAGsC;AACtC,eAAO,MAAM,6BAA6B,qBAAqB,CAAC;AAoChE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAc1I;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CA2B/I;AAkDD,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAgB7H"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AA2VpD;;;2BAG2B;AAC3B,wBAAgB,sBAAsB,IAAI,MAAM,CAsC/C"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAqWpD;;;2BAG2B;AAC3B,wBAAgB,sBAAsB,IAAI,MAAM,CAsC/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotCache.d.ts","sourceRoot":"","sources":["../../src/server/snapshotCache.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,oBAAoB,CAAC;AAyBvE;;;oEAGoE;AACpE,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA8BvH;AAED;;;6BAG6B;AAC7B,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CASvH;AAED;;sDAEsD;AACtD,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAExI;AAED;;eAEe;AACf,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAOhH;AA4HD;;;uEAGuE;AACvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAShG;AAED;;;mDAGmD;AACnD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpE;AAED;;;;2DAI2D;AAC3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOlD;AAED;2DAC2D;AAC3D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAWA;AAED;;mEAEmE;AACnE,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAUlE"}
1
+ {"version":3,"file":"snapshotCache.d.ts","sourceRoot":"","sources":["../../src/server/snapshotCache.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,oBAAoB,CAAC;AA2BvE;;;oEAGoE;AACpE,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA8BvH;AAED;;;6BAG6B;AAC7B,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CASvH;AAED;;sDAEsD;AACtD,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAExI;AAED;;eAEe;AACf,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAOhH;AA4HD;;;uEAGuE;AACvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAShG;AAED;;;mDAGmD;AACnD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpE;AAED;;;;2DAI2D;AAC3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOlD;AAED;2DAC2D;AAC3D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAWA;AAED;;mEAEmE;AACnE,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAUlE"}
@@ -1 +1 @@
1
- {"version":3,"file":"timeSeries.d.ts","sourceRoot":"","sources":["../../src/server/timeSeries.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAe,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,EAEL,KAAK,aAAa,EAClB,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,CAAC;AAExD,MAAM,WAAW,MAAM;IACrB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX;;;;6DAIyD;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX;;;4EAGwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf;AA8GD;;;;;;8DAM8D;AAC9D,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,qBAAqB,CAAC;IAAC,aAAa,EAAE,aAAa,CAAA;CAAE,GAAG,MAAM,EAAE,CAazI;AAkED,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,eAAe,EAAE,CAapB"}
1
+ {"version":3,"file":"timeSeries.d.ts","sourceRoot":"","sources":["../../src/server/timeSeries.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAe,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,EAEL,KAAK,aAAa,EAClB,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,CAAC;AAExD,MAAM,WAAW,MAAM;IACrB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX;;;;6DAIyD;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX;;;4EAGwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf;AAiHD;;;;;;8DAM8D;AAC9D,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,qBAAqB,CAAC;IAAC,aAAa,EAAE,aAAa,CAAA;CAAE,GAAG,MAAM,EAAE,CAazI;AAkED,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,eAAe,EAAE,CAapB"}
package/dist/server.cjs CHANGED
@@ -21,7 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
- const require_shared = require("./shared-KHOWwwiZ.cjs");
24
+ const require_shared = require("./shared-BpFVwa6Y.cjs");
25
25
  let express = require("express");
26
26
  let node_crypto = require("node:crypto");
27
27
  let node_fs = require("node:fs");
@@ -31,18 +31,36 @@ let _mulmoclaude_core_files = require("@mulmoclaude/core/files");
31
31
  //#region src/server/bodyFields.ts
32
32
  var optionalString = (value) => typeof value === "string" ? value : void 0;
33
33
  var optionalRecord = (value) => require_shared.isRecord(value) ? value : void 0;
34
+ var YEAR_MONTH_RE = /^\d{4}-(0[1-9]|1[0-2])$/;
35
+ var YEAR_MONTH_DAY_RE = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
36
+ /** `YYYY-MM-DD` that names a day the calendar actually has. The regex alone
37
+ * admits `2026-02-30`, and `Date.UTC` rolls that forward to March instead of
38
+ * refusing it, so the round trip is what says the date is real. */
39
+ var isCalendarDate = (value) => {
40
+ if (!YEAR_MONTH_DAY_RE.test(value)) return false;
41
+ const [year, month, day] = value.split("-").map(Number);
42
+ if (year === void 0 || month === void 0 || day === void 0) return false;
43
+ return new Date(Date.UTC(year, month - 1, day)).getUTCDate() === day;
44
+ };
34
45
  /** Rebuilt field by field rather than narrowed with a predicate, so the
35
46
  * returned object is one this function actually proved. A half-formed
36
47
  * `{ kind: "month" }` reads as absent and the caller raises its own
37
48
  * "period is required" — previously it reached the report builders and
38
- * produced an `undefined-01` date. */
49
+ * produced an `undefined-01` date.
50
+ *
51
+ * The FORMAT is checked here too, not just the type: `typeof === "string"`
52
+ * let `{ kind: "month", period: "banana" }` through, which came back as a
53
+ * balance sheet dated `"banana-NaN"` and made the snapshot cache write
54
+ * `banana.json` / `0NaN-NaN.json` into the book (#2765). Malformed reads as
55
+ * absent so it lands on the caller's existing 400, which already spells out
56
+ * both accepted shapes for the LLM to repair its payload from. */
39
57
  var optionalReportPeriod = (value) => {
40
58
  const period = optionalRecord(value);
41
- if (period?.kind === "month" && typeof period.period === "string") return {
59
+ if (period?.kind === "month" && typeof period.period === "string" && YEAR_MONTH_RE.test(period.period)) return {
42
60
  kind: "month",
43
61
  period: period.period
44
62
  };
45
- if (period?.kind === "range" && typeof period.from === "string" && typeof period.to === "string") return {
63
+ if (period?.kind === "range" && typeof period.from === "string" && typeof period.to === "string" && isCalendarDate(period.from) && isCalendarDate(period.to)) return {
46
64
  kind: "range",
47
65
  from: period.from,
48
66
  to: period.to
@@ -118,6 +136,7 @@ function localDateString(now = /* @__PURE__ */ new Date()) {
118
136
  function isValidCalendarDate(date) {
119
137
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) return false;
120
138
  const [year, month, day] = date.split("-").map((segment) => parseInt(segment, 10));
139
+ if (year === void 0 || month === void 0 || day === void 0) return false;
121
140
  const parsed = new Date(Date.UTC(year, month - 1, day));
122
141
  return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month - 1 && parsed.getUTCDate() === day;
123
142
  }
@@ -622,6 +641,7 @@ async function invalidateSnapshotsFrom(bookId, fromPeriod, workspaceRoot) {
622
641
  const match = /^(\d{4}-\d{2})\.json$/.exec(name);
623
642
  if (!match) continue;
624
643
  const [, period] = match;
644
+ if (period === void 0) continue;
625
645
  if (period >= fromPeriod) {
626
646
  await node_fs.promises.rm(node_path.default.join(snapshotsDir(bookId, workspaceRoot), name), { force: true });
627
647
  removed.push(period);
@@ -858,48 +878,38 @@ function computeCurrentEarnings(accounts, balanceByCode) {
858
878
  }
859
879
  return earnings;
860
880
  }
881
+ function buildBalanceSheetSection(type, accounts, balanceByCode, currentEarnings) {
882
+ const rows = accounts.filter((account) => account.type === type).map((account) => ({
883
+ accountCode: account.code,
884
+ accountName: account.name,
885
+ balance: naturalSign$1(type, balanceByCode.get(account.code) ?? 0)
886
+ })).filter((row) => Math.abs(row.balance) > ZERO_TOLERANCE);
887
+ if (type === "equity" && Math.abs(currentEarnings) > ZERO_TOLERANCE) rows.push({
888
+ accountCode: CURRENT_EARNINGS_ACCOUNT_CODE,
889
+ accountName: "Current period earnings",
890
+ balance: currentEarnings
891
+ });
892
+ return {
893
+ type,
894
+ rows,
895
+ total: rows.reduce((sum, row) => sum + row.balance, 0)
896
+ };
897
+ }
861
898
  function buildBalanceSheet(input) {
862
899
  const balanceByCode = new Map(input.balances.map((row) => [row.accountCode, row.netDebit]));
863
900
  const currentEarnings = computeCurrentEarnings(input.accounts, balanceByCode);
864
- const sections = [];
865
- for (const type of [
866
- "asset",
867
- "liability",
868
- "equity"
869
- ]) {
870
- const rows = [];
871
- let total = 0;
872
- for (const account of input.accounts) {
873
- if (account.type !== type) continue;
874
- const presented = naturalSign$1(type, balanceByCode.get(account.code) ?? 0);
875
- if (Math.abs(presented) <= ZERO_TOLERANCE) continue;
876
- rows.push({
877
- accountCode: account.code,
878
- accountName: account.name,
879
- balance: presented
880
- });
881
- total += presented;
882
- }
883
- if (type === "equity" && Math.abs(currentEarnings) > ZERO_TOLERANCE) {
884
- rows.push({
885
- accountCode: CURRENT_EARNINGS_ACCOUNT_CODE,
886
- accountName: "Current period earnings",
887
- balance: currentEarnings
888
- });
889
- total += currentEarnings;
890
- }
891
- sections.push({
892
- type,
893
- rows,
894
- total
895
- });
896
- }
897
- const assetTotal = sections[0].total;
898
- const liabEquityTotal = sections[1].total + sections[2].total;
901
+ const section = (type) => buildBalanceSheetSection(type, input.accounts, balanceByCode, currentEarnings);
902
+ const assets = section("asset");
903
+ const liabilities = section("liability");
904
+ const equity = section("equity");
899
905
  return {
900
906
  asOf: input.asOf,
901
- sections,
902
- imbalance: assetTotal - liabEquityTotal
907
+ sections: [
908
+ assets,
909
+ liabilities,
910
+ equity
911
+ ],
912
+ imbalance: assets.total - (liabilities.total + equity.total)
903
913
  };
904
914
  }
905
915
  function buildProfitLoss(input) {
@@ -1001,7 +1011,7 @@ function fmtYmd(year, month, day) {
1001
1011
  return `${year}-${pad2(month)}-${pad2(day)}`;
1002
1012
  }
1003
1013
  function parseYmd(value) {
1004
- const [year, month, day] = value.split("-").map((segment) => parseInt(segment, 10));
1014
+ const [year = NaN, month = NaN, day = NaN] = value.split("-").map((segment) => parseInt(segment, 10));
1005
1015
  return {
1006
1016
  year,
1007
1017
  month,
@@ -1181,7 +1191,7 @@ function publishBooksChanged() {
1181
1191
  //#endregion
1182
1192
  //#region src/server/snapshotCache.ts
1183
1193
  function previousPeriod(period) {
1184
- const [year, month] = period.split("-").map((segment) => parseInt(segment, 10));
1194
+ const [year = NaN, month = NaN] = period.split("-").map((segment) => parseInt(segment, 10));
1185
1195
  if (month === 1) return `${(year - 1).toString().padStart(4, "0")}-12`;
1186
1196
  return `${year.toString().padStart(4, "0")}-${(month - 1).toString().padStart(2, "0")}`;
1187
1197
  }
@@ -1207,12 +1217,12 @@ async function buildEmptySnapshot(bookId, period, workspaceRoot) {
1207
1217
  async function getOrBuildSnapshot(bookId, period, workspaceRoot) {
1208
1218
  const cached = await readSnapshot(bookId, period, workspaceRoot);
1209
1219
  if (cached) return cached;
1210
- const periods = await listJournalPeriods(bookId, workspaceRoot);
1211
- if (periods.length === 0 || period < periods[0]) return buildEmptySnapshot(bookId, period, workspaceRoot);
1220
+ const [earliestPeriod] = await listJournalPeriods(bookId, workspaceRoot);
1221
+ if (earliestPeriod === void 0 || period < earliestPeriod) return buildEmptySnapshot(bookId, period, workspaceRoot);
1212
1222
  const { entries } = await readJournalMonth(bookId, period, workspaceRoot);
1213
1223
  const monthDelta = aggregateBalances(entries);
1214
1224
  let priorBalances = [];
1215
- if (period > periods[0]) priorBalances = (await getOrBuildSnapshot(bookId, previousPeriod(period), workspaceRoot)).balances;
1225
+ if (period > earliestPeriod) priorBalances = (await getOrBuildSnapshot(bookId, previousPeriod(period), workspaceRoot)).balances;
1216
1226
  const snap = {
1217
1227
  period,
1218
1228
  balances: mergeBalances(priorBalances, monthDelta),
@@ -1947,7 +1957,7 @@ async function setOpeningBalances(input, workspaceRoot) {
1947
1957
  }
1948
1958
  function endDateOfPeriod(period) {
1949
1959
  if (period.kind === "month") {
1950
- const [year, month] = period.period.split("-").map((segment) => parseInt(segment, 10));
1960
+ const [year = NaN, month = NaN] = period.period.split("-").map((segment) => parseInt(segment, 10));
1951
1961
  const last = new Date(Date.UTC(year, month, 0)).getUTCDate();
1952
1962
  return `${period.period}-${String(last).padStart(2, "0")}`;
1953
1963
  }
@@ -2116,6 +2126,7 @@ async function handleGetReport(rest) {
2116
2126
  const periodInput = optionalReportPeriod(rest.period);
2117
2127
  const bookId = optionalString(rest.bookId);
2118
2128
  const periodRequired = (label) => new AccountingError(400, `${label}: period is required — { kind: "month", period: "YYYY-MM" } or { kind: "range", from: "YYYY-MM-DD", to: "YYYY-MM-DD" }`);
2129
+ if (rest.period !== void 0 && rest.period !== null && !periodInput) throw periodRequired(`getReport ${kind || "(no kind)"}`);
2119
2130
  if (kind === "balance") {
2120
2131
  if (!periodInput) throw periodRequired("getReport balance");
2121
2132
  return getBalanceSheetReport({
@@ -2241,11 +2252,11 @@ var MESSAGE_BUILDERS = {
2241
2252
  },
2242
2253
  [require_shared.ACCOUNTING_ACTIONS.addEntries]: (fields) => {
2243
2254
  const entries = (require_shared.isUnknownArray(fields.entries) ? fields.entries : []).map(describeEntry);
2244
- if (entries.length === 0) return "Posted 0 journal entries.";
2245
- if (entries.length === 1) {
2246
- const [entry] = entries;
2247
- const idFragment = entry.id ? ` (id: ${entry.id})` : "";
2248
- return `Posted a journal entry on ${entry.date ?? "the requested date"}${idFragment}.`;
2255
+ const [firstEntry, ...furtherEntries] = entries;
2256
+ if (!firstEntry) return "Posted 0 journal entries.";
2257
+ if (furtherEntries.length === 0) {
2258
+ const idFragment = firstEntry.id ? ` (id: ${firstEntry.id})` : "";
2259
+ return `Posted a journal entry on ${firstEntry.date ?? "the requested date"}${idFragment}.`;
2249
2260
  }
2250
2261
  const summary = entries.map((entry) => `${entry.date ?? "?"} (id: ${entry.id ?? "?"})`).join(", ");
2251
2262
  return `Posted ${entries.length} journal entries: ${summary}.`;
@@ -2273,14 +2284,22 @@ var MESSAGE_BUILDERS = {
2273
2284
  return `Updated ${bookName ? JSON.stringify(bookName) : "the book"}${country ? ` (country: ${country})` : ""}.`;
2274
2285
  }
2275
2286
  };
2287
+ /** Read a record entry under a user/LLM-controlled key. The
2288
+ * `Object.hasOwn` gate is load-bearing: a bare `record[key]` resolves
2289
+ * inherited prototype members, so a crafted action ("constructor",
2290
+ * "toString") would dispatch to an unexpected target instead of
2291
+ * reading as absent. */
2292
+ function ownEntry(record, key) {
2293
+ return Object.hasOwn(record, key) ? record[key] : void 0;
2294
+ }
2276
2295
  function previewMessage(action, fields) {
2277
- const head = Object.hasOwn(MESSAGE_BUILDERS, action) ? MESSAGE_BUILDERS[action](fields) : void 0;
2296
+ const head = ownEntry(MESSAGE_BUILDERS, action)?.(fields);
2278
2297
  return head ? `${head} ${VIEW_VISIBLE_TRAILER}` : VIEW_VISIBLE_TRAILER;
2279
2298
  }
2280
2299
  async function dispatch(body) {
2281
2300
  const { action, ...rest } = body;
2282
- if (!Object.hasOwn(ACTION_HANDLERS, action)) throw new AccountingError(400, `unknown action ${JSON.stringify(action)}`);
2283
- const handler = ACTION_HANDLERS[action];
2301
+ const handler = ownEntry(ACTION_HANDLERS, action);
2302
+ if (!handler) throw new AccountingError(400, `unknown action ${JSON.stringify(action)}`);
2284
2303
  const result = await handler(rest);
2285
2304
  const handlerFields = require_shared.isRecord(result) ? result : { value: result };
2286
2305
  const dataField = PREVIEW_ACTIONS.has(action) ? { data: {