@atcn/subledger 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.
@@ -0,0 +1,280 @@
1
+ import { z } from "zod";
2
+ /** Agent Work Subledger record shapes (PRD v1.2 §6-§7). Amounts are integer minor units; currencies are ISO 4217. */
3
+ export declare const Currency: z.ZodString;
4
+ export declare const Minor: z.ZodNumber;
5
+ export declare const FINANCIAL_EVENT_TYPES: readonly ["quote", "invoice", "charge", "payment_reported", "refund", "reversal", "fee", "credit", "adjustment", "fx_rate"];
6
+ export type FinancialEventType = (typeof FINANCIAL_EVENT_TYPES)[number];
7
+ /** Normalized status vocabulary; the provider's original status is always kept beside it. */
8
+ export declare const NORMALIZED_STATUSES: readonly ["quoted", "issued", "pending", "reported_paid", "failed", "refunded", "reversed", "void", "unknown"];
9
+ export declare const PAYERS: readonly ["buyer", "provider", "other"];
10
+ export declare const DELIVERY_EVENT_TYPES: readonly ["acceptance", "completion", "partial_completion", "cancellation", "provider_failure", "terms_update", "correction"];
11
+ export type DeliveryEventType = (typeof DELIVERY_EVENT_TYPES)[number];
12
+ /**
13
+ * Who made a delivery statement. Callers record "buyer" or "provider" (relayed by the buyer). The other values are
14
+ * recorded only from clearing-network events: "clearing_policy" for a decision computed by the agreed policy from
15
+ * submitted evidence, "dispute_reviewer" for a decision by the human reviewer named in the terms, and
16
+ * "clearing_network" for automatic rules such as expiry.
17
+ */
18
+ export declare const CLAIM_ASSERTERS: readonly ["buyer", "provider", "clearing_policy", "dispute_reviewer", "clearing_network"];
19
+ export type ClaimAsserter = (typeof CLAIM_ASSERTERS)[number];
20
+ export declare const EXCEPTION_KINDS: readonly ["budget_overrun", "unmatched_charge", "ambiguous_match", "missing_receipt", "duplicate_event", "amount_mismatch", "currency_mismatch", "stale_quote", "refund_after_close", "allocation_changed_after_close", "incomplete_lineage"];
21
+ export type ExceptionKind = (typeof EXCEPTION_KINDS)[number];
22
+ /** Trust labels kept separate on every screen and export (PRD §16 "Identity assurance"). Never collapsed into "verified". */
23
+ export declare const ASSURANCE_LABELS: readonly ["issuer_signed", "buyer_recorded", "network_recorded", "recipient_viewed", "link_authenticated_response", "provider_identity_bound", "provider_key_signed", "contested", "superseded"];
24
+ export type AssuranceLabel = (typeof ASSURANCE_LABELS)[number];
25
+ export declare const RESPONSE_TYPES: readonly ["acknowledge_view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
26
+ export type ResponseType = (typeof RESPONSE_TYPES)[number];
27
+ export declare const SHARE_ACTIONS: readonly ["view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
28
+ export type ShareAction = (typeof SHARE_ACTIONS)[number];
29
+ /** Receipt fields a provider may attest to or contest. Attesting one never implies the others (acceptance 16). */
30
+ export declare const ATTESTABLE_FIELDS: readonly ["delivery.status", "delivery.evidence", "scope.terms_digest", "financial.amounts", "financial.status"];
31
+ export type AttestableField = (typeof ATTESTABLE_FIELDS)[number];
32
+ /** Evidence stays in its source system; only references and digests are stored. Script-capable schemes are refused. */
33
+ export declare const EvidenceRefSchema: z.ZodObject<{
34
+ uri: z.ZodString;
35
+ digest: z.ZodNullable<z.ZodString>;
36
+ evidence_type: z.ZodString;
37
+ }, z.core.$strip>;
38
+ export type EvidenceRef = z.infer<typeof EvidenceRefSchema>;
39
+ export declare const TaskInputSchema: z.ZodObject<{
40
+ external_ref: z.ZodString;
41
+ currency: z.ZodString;
42
+ budget_minor: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
43
+ customer_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
44
+ project_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
45
+ cost_center: z.ZodDefault<z.ZodNullable<z.ZodString>>;
46
+ scope_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
47
+ shared_description: z.ZodDefault<z.ZodNullable<z.ZodString>>;
48
+ retrospective: z.ZodDefault<z.ZodBoolean>;
49
+ occurred_at: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
50
+ }, z.core.$strip>;
51
+ export type TaskInput = z.infer<typeof TaskInputSchema>;
52
+ export declare const ProviderInputSchema: z.ZodObject<{
53
+ name: z.ZodString;
54
+ provider_own_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
55
+ domain: z.ZodDefault<z.ZodNullable<z.ZodString>>;
56
+ }, z.core.$strip>;
57
+ export declare const DelegationInputSchema: z.ZodObject<{
58
+ parent_delegation_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
59
+ provider_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
60
+ provider_name_stated: z.ZodDefault<z.ZodNullable<z.ZodString>>;
61
+ provider_own_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
62
+ external_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
63
+ provider_job_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
64
+ scope_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
65
+ shared_description: z.ZodDefault<z.ZodNullable<z.ZodString>>;
66
+ currency: z.ZodString;
67
+ quoted_max_minor: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
68
+ quote_basis: z.ZodDefault<z.ZodNullable<z.ZodString>>;
69
+ quote_valid_until: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
70
+ accepted_amount_minor: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
71
+ terms_digest: z.ZodDefault<z.ZodNullable<z.ZodString>>;
72
+ expected_delivery: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
73
+ downstream_visibility: z.ZodDefault<z.ZodEnum<{
74
+ unknown: "unknown";
75
+ disclosed: "disclosed";
76
+ none: "none";
77
+ }>>;
78
+ retrospective: z.ZodDefault<z.ZodBoolean>;
79
+ }, z.core.$strip>;
80
+ export type DelegationInput = z.infer<typeof DelegationInputSchema>;
81
+ export declare const DelegationEventInputSchema: z.ZodObject<{
82
+ type: z.ZodEnum<{
83
+ acceptance: "acceptance";
84
+ completion: "completion";
85
+ partial_completion: "partial_completion";
86
+ cancellation: "cancellation";
87
+ provider_failure: "provider_failure";
88
+ terms_update: "terms_update";
89
+ correction: "correction";
90
+ }>;
91
+ asserted_by: z.ZodDefault<z.ZodEnum<{
92
+ buyer: "buyer";
93
+ provider: "provider";
94
+ }>>;
95
+ note: z.ZodDefault<z.ZodNullable<z.ZodString>>;
96
+ evidence: z.ZodDefault<z.ZodArray<z.ZodObject<{
97
+ uri: z.ZodString;
98
+ digest: z.ZodNullable<z.ZodString>;
99
+ evidence_type: z.ZodString;
100
+ }, z.core.$strip>>>;
101
+ terms: z.ZodDefault<z.ZodNullable<z.ZodObject<{
102
+ quoted_max_minor: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
103
+ accepted_amount_minor: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
104
+ quote_basis: z.ZodOptional<z.ZodNullable<z.ZodString>>;
105
+ quote_valid_until: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
106
+ terms_digest: z.ZodOptional<z.ZodNullable<z.ZodString>>;
107
+ expected_delivery: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
108
+ downstream_visibility: z.ZodOptional<z.ZodEnum<{
109
+ unknown: "unknown";
110
+ disclosed: "disclosed";
111
+ none: "none";
112
+ }>>;
113
+ }, z.core.$strip>>>;
114
+ supersedes_event_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
115
+ reason: z.ZodDefault<z.ZodNullable<z.ZodString>>;
116
+ retrospective: z.ZodDefault<z.ZodBoolean>;
117
+ occurred_at: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
118
+ }, z.core.$strip>;
119
+ export type DelegationEventInput = z.infer<typeof DelegationEventInputSchema>;
120
+ export declare const FxSchema: z.ZodObject<{
121
+ base_currency: z.ZodString;
122
+ quote_currency: z.ZodString;
123
+ rate_numerator: z.ZodNumber;
124
+ rate_denominator: z.ZodNumber;
125
+ }, z.core.$strip>;
126
+ export type Fx = z.infer<typeof FxSchema>;
127
+ export declare const FinancialEventInputSchema: z.ZodObject<{
128
+ type: z.ZodEnum<{
129
+ quote: "quote";
130
+ invoice: "invoice";
131
+ charge: "charge";
132
+ payment_reported: "payment_reported";
133
+ refund: "refund";
134
+ reversal: "reversal";
135
+ fee: "fee";
136
+ credit: "credit";
137
+ adjustment: "adjustment";
138
+ fx_rate: "fx_rate";
139
+ }>;
140
+ source: z.ZodString;
141
+ source_event_id: z.ZodString;
142
+ provider_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
143
+ provider_reference: z.ZodDefault<z.ZodNullable<z.ZodString>>;
144
+ amount_minor: z.ZodNumber;
145
+ currency: z.ZodString;
146
+ event_date: z.ZodISODateTime;
147
+ provider_status: z.ZodDefault<z.ZodNullable<z.ZodString>>;
148
+ normalized_status: z.ZodDefault<z.ZodEnum<{
149
+ quoted: "quoted";
150
+ issued: "issued";
151
+ pending: "pending";
152
+ reported_paid: "reported_paid";
153
+ failed: "failed";
154
+ refunded: "refunded";
155
+ reversed: "reversed";
156
+ void: "void";
157
+ unknown: "unknown";
158
+ }>>;
159
+ evidence: z.ZodDefault<z.ZodNullable<z.ZodObject<{
160
+ uri: z.ZodString;
161
+ digest: z.ZodNullable<z.ZodString>;
162
+ evidence_type: z.ZodString;
163
+ }, z.core.$strip>>>;
164
+ retrospective: z.ZodDefault<z.ZodBoolean>;
165
+ payer: z.ZodDefault<z.ZodEnum<{
166
+ buyer: "buyer";
167
+ provider: "provider";
168
+ other: "other";
169
+ }>>;
170
+ liability_owner: z.ZodDefault<z.ZodNullable<z.ZodString>>;
171
+ economic_event_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
172
+ included_in_event_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
173
+ reverses_event_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
174
+ settles_event_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
175
+ fx: z.ZodDefault<z.ZodNullable<z.ZodObject<{
176
+ base_currency: z.ZodString;
177
+ quote_currency: z.ZodString;
178
+ rate_numerator: z.ZodNumber;
179
+ rate_denominator: z.ZodNumber;
180
+ }, z.core.$strip>>>;
181
+ reason: z.ZodDefault<z.ZodNullable<z.ZodString>>;
182
+ match: z.ZodDefault<z.ZodObject<{
183
+ task_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
184
+ delegation_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
185
+ task_external_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
186
+ delegation_external_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
187
+ provider_job_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
188
+ }, z.core.$strip>>;
189
+ }, z.core.$strip>;
190
+ export type FinancialEventInput = z.input<typeof FinancialEventInputSchema>;
191
+ /** A stored financial event exactly as hashed into exports. */
192
+ export interface FinancialEventRecord {
193
+ financial_event_id: string;
194
+ type: FinancialEventType;
195
+ source: string;
196
+ source_event_id: string;
197
+ provider_id: string | null;
198
+ provider_reference: string | null;
199
+ amount_minor: number;
200
+ currency: string;
201
+ event_date: string;
202
+ imported_at: string;
203
+ provider_status: string | null;
204
+ normalized_status: (typeof NORMALIZED_STATUSES)[number];
205
+ evidence: EvidenceRef | null;
206
+ retrospective: boolean;
207
+ payer: (typeof PAYERS)[number];
208
+ liability_owner: string | null;
209
+ economic_event_id: string | null;
210
+ included_in_event_id: string | null;
211
+ reverses_event_id: string | null;
212
+ settles_event_id: string | null;
213
+ fx: Fx | null;
214
+ reason: string | null;
215
+ }
216
+ export declare const AllocationTargetSchema: z.ZodObject<{
217
+ type: z.ZodEnum<{
218
+ cost_center: "cost_center";
219
+ task: "task";
220
+ delegation: "delegation";
221
+ unallocated: "unallocated";
222
+ }>;
223
+ id: z.ZodNullable<z.ZodString>;
224
+ }, z.core.$strip>;
225
+ export type AllocationTarget = z.infer<typeof AllocationTargetSchema>;
226
+ export interface AllocationLine {
227
+ target: AllocationTarget;
228
+ amount_minor: number;
229
+ }
230
+ export declare const AllocationInputSchema: z.ZodObject<{
231
+ lines: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodObject<{
232
+ target: z.ZodObject<{
233
+ type: z.ZodEnum<{
234
+ cost_center: "cost_center";
235
+ task: "task";
236
+ delegation: "delegation";
237
+ unallocated: "unallocated";
238
+ }>;
239
+ id: z.ZodNullable<z.ZodString>;
240
+ }, z.core.$strip>;
241
+ amount_minor: z.ZodNumber;
242
+ }, z.core.$strip>>>>;
243
+ rule: z.ZodDefault<z.ZodNullable<z.ZodObject<{
244
+ rule_id: z.ZodString;
245
+ version: z.ZodNumber;
246
+ }, z.core.$strip>>>;
247
+ reason: z.ZodString;
248
+ }, z.core.$strip>;
249
+ export declare const AllocationRuleInputSchema: z.ZodObject<{
250
+ rule_id: z.ZodString;
251
+ match: z.ZodObject<{
252
+ provider_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
253
+ task_external_ref: z.ZodDefault<z.ZodNullable<z.ZodString>>;
254
+ cost_center: z.ZodDefault<z.ZodNullable<z.ZodString>>;
255
+ }, z.core.$strip>;
256
+ splits: z.ZodArray<z.ZodObject<{
257
+ target: z.ZodObject<{
258
+ type: z.ZodEnum<{
259
+ cost_center: "cost_center";
260
+ task: "task";
261
+ delegation: "delegation";
262
+ unallocated: "unallocated";
263
+ }>;
264
+ id: z.ZodNullable<z.ZodString>;
265
+ }, z.core.$strip>;
266
+ weight_bps: z.ZodNumber;
267
+ }, z.core.$strip>>;
268
+ }, z.core.$strip>;
269
+ export interface DelegationNode {
270
+ delegation_id: string;
271
+ parent_delegation_id: string | null;
272
+ currency: string;
273
+ quoted_max_minor: number | null;
274
+ accepted_amount_minor: number | null;
275
+ }
276
+ export interface RootNode {
277
+ task_id: string;
278
+ currency: string;
279
+ budget_minor: number | null;
280
+ }
package/dist/types.js ADDED
@@ -0,0 +1,188 @@
1
+ import { z } from "zod";
2
+ /** Agent Work Subledger record shapes (PRD v1.2 §6-§7). Amounts are integer minor units; currencies are ISO 4217. */
3
+ export const Currency = z.string().regex(/^[A-Z]{3}$/, "ISO 4217 currency code");
4
+ export const Minor = z.number().int().refine(Number.isSafeInteger, "amount must be a safe integer");
5
+ const Iso = z.iso.datetime();
6
+ const Digest = z.string().regex(/^sha256:[0-9a-f]{64}$/);
7
+ export const FINANCIAL_EVENT_TYPES = ["quote", "invoice", "charge", "payment_reported", "refund", "reversal", "fee", "credit", "adjustment", "fx_rate"];
8
+ /** Normalized status vocabulary; the provider's original status is always kept beside it. */
9
+ export const NORMALIZED_STATUSES = ["quoted", "issued", "pending", "reported_paid", "failed", "refunded", "reversed", "void", "unknown"];
10
+ export const PAYERS = ["buyer", "provider", "other"];
11
+ export const DELIVERY_EVENT_TYPES = ["acceptance", "completion", "partial_completion", "cancellation", "provider_failure", "terms_update", "correction"];
12
+ /**
13
+ * Who made a delivery statement. Callers record "buyer" or "provider" (relayed by the buyer). The other values are
14
+ * recorded only from clearing-network events: "clearing_policy" for a decision computed by the agreed policy from
15
+ * submitted evidence, "dispute_reviewer" for a decision by the human reviewer named in the terms, and
16
+ * "clearing_network" for automatic rules such as expiry.
17
+ */
18
+ export const CLAIM_ASSERTERS = ["buyer", "provider", "clearing_policy", "dispute_reviewer", "clearing_network"];
19
+ export const EXCEPTION_KINDS = [
20
+ "budget_overrun",
21
+ "unmatched_charge",
22
+ "ambiguous_match",
23
+ "missing_receipt",
24
+ "duplicate_event",
25
+ "amount_mismatch",
26
+ "currency_mismatch",
27
+ "stale_quote",
28
+ "refund_after_close",
29
+ "allocation_changed_after_close",
30
+ "incomplete_lineage",
31
+ ];
32
+ /** Trust labels kept separate on every screen and export (PRD §16 "Identity assurance"). Never collapsed into "verified". */
33
+ export const ASSURANCE_LABELS = [
34
+ "issuer_signed",
35
+ "buyer_recorded",
36
+ /** Recorded automatically by the clearing network from a signed network event the claim cites (schema 1.3). */
37
+ "network_recorded",
38
+ "recipient_viewed",
39
+ "link_authenticated_response",
40
+ "provider_identity_bound",
41
+ "provider_key_signed",
42
+ "contested",
43
+ "superseded",
44
+ ];
45
+ export const RESPONSE_TYPES = ["acknowledge_view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
46
+ export const SHARE_ACTIONS = ["view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
47
+ /** Receipt fields a provider may attest to or contest. Attesting one never implies the others (acceptance 16). */
48
+ export const ATTESTABLE_FIELDS = ["delivery.status", "delivery.evidence", "scope.terms_digest", "financial.amounts", "financial.status"];
49
+ /** Evidence stays in its source system; only references and digests are stored. Script-capable schemes are refused. */
50
+ export const EvidenceRefSchema = z.object({
51
+ uri: z
52
+ .string()
53
+ .min(1)
54
+ .max(2048)
55
+ .regex(/^(https:\/\/|urn:|s3:\/\/|gs:\/\/)/, "evidence uri must use https, urn, s3, or gs"),
56
+ digest: Digest.nullable(),
57
+ evidence_type: z.string().min(1).max(100),
58
+ });
59
+ export const TaskInputSchema = z.object({
60
+ external_ref: z.string().min(1).max(200),
61
+ currency: Currency,
62
+ budget_minor: Minor.nonnegative().nullable().default(null),
63
+ customer_ref: z.string().max(200).nullable().default(null),
64
+ project_ref: z.string().max(200).nullable().default(null),
65
+ cost_center: z.string().max(200).nullable().default(null),
66
+ scope_ref: z.string().max(500).nullable().default(null),
67
+ shared_description: z.string().max(1000).nullable().default(null),
68
+ retrospective: z.boolean().default(false),
69
+ occurred_at: Iso.nullable().default(null),
70
+ });
71
+ export const ProviderInputSchema = z.object({
72
+ name: z.string().min(1).max(200),
73
+ provider_own_id: z.string().max(200).nullable().default(null),
74
+ domain: z.string().max(253).nullable().default(null),
75
+ });
76
+ export const DelegationInputSchema = z.object({
77
+ parent_delegation_id: z.string().nullable().default(null),
78
+ provider_id: z.string().nullable().default(null),
79
+ provider_name_stated: z.string().max(200).nullable().default(null),
80
+ provider_own_id: z.string().max(200).nullable().default(null),
81
+ external_ref: z.string().max(200).nullable().default(null),
82
+ provider_job_ref: z.string().max(200).nullable().default(null),
83
+ scope_ref: z.string().max(500).nullable().default(null),
84
+ shared_description: z.string().max(1000).nullable().default(null),
85
+ currency: Currency,
86
+ quoted_max_minor: Minor.nonnegative().nullable().default(null),
87
+ quote_basis: z.string().max(200).nullable().default(null),
88
+ quote_valid_until: Iso.nullable().default(null),
89
+ accepted_amount_minor: Minor.nonnegative().nullable().default(null),
90
+ /** Digest of the agreed terms document, which stays in the operator's systems. */
91
+ terms_digest: Digest.nullable().default(null),
92
+ expected_delivery: Iso.nullable().default(null),
93
+ /** Whether the provider disclosed its own subdelegations. Absent data stays "unknown" (acceptance 24). */
94
+ downstream_visibility: z.enum(["unknown", "disclosed", "none"]).default("unknown"),
95
+ retrospective: z.boolean().default(false),
96
+ });
97
+ export const DelegationEventInputSchema = z.object({
98
+ type: z.enum(DELIVERY_EVENT_TYPES),
99
+ /** Who made the statement. The buyer records it either way; a provider statement relayed by the buyer is not provider-verified. */
100
+ asserted_by: z.enum(["buyer", "provider"]).default("buyer"),
101
+ note: z.string().max(2000).nullable().default(null),
102
+ evidence: z.array(EvidenceRefSchema).max(20).default([]),
103
+ /** terms_update only: new commercial terms (amount changes create new events, PRD §6). */
104
+ terms: z
105
+ .object({
106
+ quoted_max_minor: Minor.nonnegative().nullable().optional(),
107
+ accepted_amount_minor: Minor.nonnegative().nullable().optional(),
108
+ quote_basis: z.string().max(200).nullable().optional(),
109
+ quote_valid_until: Iso.nullable().optional(),
110
+ terms_digest: Digest.nullable().optional(),
111
+ expected_delivery: Iso.nullable().optional(),
112
+ downstream_visibility: z.enum(["unknown", "disclosed", "none"]).optional(),
113
+ })
114
+ .nullable()
115
+ .default(null),
116
+ /** correction only: the superseded event and the reason. */
117
+ supersedes_event_id: z.string().nullable().default(null),
118
+ reason: z.string().max(2000).nullable().default(null),
119
+ retrospective: z.boolean().default(false),
120
+ occurred_at: Iso.nullable().default(null),
121
+ });
122
+ export const FxSchema = z.object({
123
+ base_currency: Currency,
124
+ quote_currency: Currency,
125
+ /** 1 base = rate_numerator / rate_denominator quote (integers only, so records stay canonical-JSON safe). */
126
+ rate_numerator: z.number().int().positive(),
127
+ rate_denominator: z.number().int().positive(),
128
+ });
129
+ export const FinancialEventInputSchema = z
130
+ .object({
131
+ type: z.enum(FINANCIAL_EVENT_TYPES),
132
+ source: z.string().min(1).max(100),
133
+ source_event_id: z.string().min(1).max(200),
134
+ provider_id: z.string().nullable().default(null),
135
+ provider_reference: z.string().max(200).nullable().default(null),
136
+ amount_minor: Minor,
137
+ currency: Currency,
138
+ event_date: Iso,
139
+ provider_status: z.string().max(100).nullable().default(null),
140
+ normalized_status: z.enum(NORMALIZED_STATUSES).default("unknown"),
141
+ evidence: EvidenceRefSchema.nullable().default(null),
142
+ retrospective: z.boolean().default(false),
143
+ payer: z.enum(PAYERS).default("buyer"),
144
+ liability_owner: z.string().max(200).nullable().default(null),
145
+ economic_event_id: z.string().max(200).nullable().default(null),
146
+ included_in_event_id: z.string().nullable().default(null),
147
+ reverses_event_id: z.string().nullable().default(null),
148
+ settles_event_id: z.string().nullable().default(null),
149
+ fx: FxSchema.nullable().default(null),
150
+ reason: z.string().max(2000).nullable().default(null),
151
+ /** Stable references used for matching. Only a unique match is applied automatically. */
152
+ match: z
153
+ .object({
154
+ task_id: z.string().nullable().default(null),
155
+ delegation_id: z.string().nullable().default(null),
156
+ task_external_ref: z.string().nullable().default(null),
157
+ delegation_external_ref: z.string().nullable().default(null),
158
+ provider_job_ref: z.string().nullable().default(null),
159
+ })
160
+ .default({ task_id: null, delegation_id: null, task_external_ref: null, delegation_external_ref: null, provider_job_ref: null }),
161
+ })
162
+ .superRefine((e, issue) => {
163
+ if (e.type !== "adjustment" && e.amount_minor < 0)
164
+ issue.addIssue({ code: "custom", path: ["amount_minor"], message: "only adjustments may be negative" });
165
+ if (e.type === "fx_rate" && !e.fx)
166
+ issue.addIssue({ code: "custom", path: ["fx"], message: "fx_rate events need fx" });
167
+ if (e.type === "reversal" && !e.reverses_event_id)
168
+ issue.addIssue({ code: "custom", path: ["reverses_event_id"], message: "reversal needs reverses_event_id" });
169
+ if (e.type === "reversal" && !e.reason)
170
+ issue.addIssue({ code: "custom", path: ["reason"], message: "reversal needs a reason" });
171
+ });
172
+ export const AllocationTargetSchema = z.object({
173
+ type: z.enum(["task", "delegation", "cost_center", "unallocated"]),
174
+ id: z.string().max(200).nullable(),
175
+ });
176
+ export const AllocationInputSchema = z
177
+ .object({
178
+ lines: z.array(z.object({ target: AllocationTargetSchema, amount_minor: Minor.nonnegative() })).max(100).nullable().default(null),
179
+ rule: z.object({ rule_id: z.string(), version: z.number().int().positive() }).nullable().default(null),
180
+ reason: z.string().min(1).max(2000),
181
+ })
182
+ .refine((a) => (a.lines === null) !== (a.rule === null), "provide exactly one of lines or rule");
183
+ export const AllocationRuleInputSchema = z.object({
184
+ rule_id: z.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
185
+ match: z.object({ provider_id: z.string().nullable().default(null), task_external_ref: z.string().nullable().default(null), cost_center: z.string().nullable().default(null) }),
186
+ /** Weights in basis points; must sum to 10000. */
187
+ splits: z.array(z.object({ target: AllocationTargetSchema, weight_bps: z.number().int().positive() })).min(1).max(50),
188
+ });
@@ -0,0 +1,30 @@
1
+ import { type PublicKeyRecord } from "@atcn/schema";
2
+ import { type OperatorKeyRecord } from "./documents.js";
3
+ export interface CheckResult {
4
+ name: string;
5
+ ok: boolean;
6
+ details: string[];
7
+ }
8
+ export interface SubledgerVerificationReport {
9
+ valid: boolean;
10
+ document_type: string | null;
11
+ /** Set when the document declares a schema version this verifier does not support; no other check ran. */
12
+ unsupported_schema_version?: string;
13
+ checks: CheckResult[];
14
+ }
15
+ export interface SubledgerVerifyOptions {
16
+ /** Published service keys trusted out of band (GET /v1/service/keys). */
17
+ trustedKeys: PublicKeyRecord[];
18
+ /** The previous revision/version, when available, to check the chain link. */
19
+ previous?: unknown;
20
+ /** The issuing operator's published keys (GET /v1/operators/{operator_id}/keys), to check countersignatures. */
21
+ operatorKeys?: OperatorKeyRecord[];
22
+ /** Fail unless at least one countersignature by the operator's own key verifies. */
23
+ requireOperatorSignature?: boolean;
24
+ /** Closure packages (GET /v1/exports/{obligation_id}) of the obligations backing linked delegations, to cross-check them. */
25
+ obligationPackages?: unknown[];
26
+ }
27
+ /** Detects the document type and verifies it offline: no network calls, no service access (acceptance 9). */
28
+ export declare function verifySubledgerDocument(input: unknown, options: SubledgerVerifyOptions): SubledgerVerificationReport;
29
+ export declare function verifyReceipt(input: unknown, options: SubledgerVerifyOptions): SubledgerVerificationReport;
30
+ export declare function verifyClosure(input: unknown, options: SubledgerVerifyOptions): SubledgerVerificationReport;