sinfactura-types 1.10.239 → 1.10.240

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.
@@ -199,18 +199,6 @@ declare global {
199
199
  */
200
200
  remaining: number;
201
201
  }
202
- /**
203
- * `GET /appointments/availability` body.
204
- *
205
- * ⚠️ `configured` disambiguates the two ways `data` comes back empty: `false`
206
- * means the type has no slotting config at all, `true` means it is configured
207
- * and every window is taken or out of range. Rendering "no availability" for
208
- * both hides a setup mistake behind a normal-looking empty day.
209
- */
210
- interface AppointmentAvailabilityResponse {
211
- data: AvailableSlot[];
212
- configured: boolean;
213
- }
214
202
  }
215
203
  /**
216
204
  * Refusals from the appointment resources a booking client reaches —
package/dist/audit.d.ts CHANGED
@@ -161,11 +161,6 @@ declare global {
161
161
  sessionId: string;
162
162
  };
163
163
  }
164
- /** APOC ("facturas apócrifas") CUIT check request. Source is ARCA's public registry snapshot imported daily into the api's `APOC` DDB partition (no per-check ARCA call). */
165
- interface ApocCheckRequest {
166
- /** The counterparty CUIT being checked (the invoice issuer, not this store). */
167
- cuit: string;
168
- }
169
164
  /** Result of an APOC registry check. Every check is logged to `FiscalAuditEvent` with operation `'ConsultarApoc'`. */
170
165
  interface ApocCheckResult {
171
166
  /** True if the CUIT appears in ARCA's APOC registry. */
package/dist/auth.d.ts CHANGED
@@ -49,26 +49,10 @@ declare global {
49
49
  error: 'ACCOUNT_LOCKED';
50
50
  retryAfterSeconds: number;
51
51
  }
52
- interface WaitlistRegisterResponse {
53
- waitlistId: string;
54
- submittedAt: number;
55
- }
56
52
  /** `GET /auth?mode=verify-invite` — the token rides the QUERY STRING, not a request body. */
57
53
  interface VerifyInviteInput {
58
54
  token: string;
59
55
  }
60
- /**
61
- * How far an invite token got, and the discriminator on every
62
- * `verify-invite` body.
63
- *
64
- * `invalid` is deliberately COARSE: an unknown token, a malformed one and a
65
- * real-but-EXPIRED one all answer `invalid`, resolved through the single
66
- * lookup `verify-invite` and `accept-invite` share so the cases cannot be
67
- * separated by timing either. ⚠️ There is no `expired` member, and adding
68
- * one would undo that — it confirms to whoever holds a leaked token that the
69
- * token was once real, and names the moment it stopped being so.
70
- */
71
- type VerifyInviteStatus = 'pending' | 'accepted' | 'revoked' | 'invalid';
72
56
  /**
73
57
  * The one branch that discloses tenant detail, and only because the caller
74
58
  * is holding a live, unexpired token issued for that tenant.
@@ -132,37 +116,6 @@ declare global {
132
116
  fullName: string;
133
117
  password: string;
134
118
  }
135
- /**
136
- * The `body.error` codes `POST /auth {mode:'accept-invite'}` can actually
137
- * return, each verified against a return site in
138
- * `stacks/lambdas/auth/_acceptInvite.ts`:
139
- *
140
- * - `VALIDATION_FAILED` (400) — `validateRequest` rejected the body against
141
- * `acceptInviteSchema`; also the WEAK-PASSWORD case, since the minimum is a
142
- * schema clause (`password: z.string().min(8)`) rather than its own code.
143
- * - `EMAIL_ALREADY_MEMBER` (400) — the invited address already belongs to a
144
- * user (`:141`, from the email-constraint transaction collision).
145
- * - `INVITATION_NOT_FOUND` (404) — no such token, or the invitation's own
146
- * store vanished mid-flight (`:145`, `:182`).
147
- * - `INVITATION_NOT_PENDING` (409) — already accepted, revoked or expired,
148
- * including losing the accept race to a concurrent request (`:150`, `:188`).
149
- * - `INVALID_ROLE` (403) — the stored role is one this anonymous route
150
- * refuses to grant; the invitation is BURNED as well as refused (`:208`).
151
- * - `PLAN_LIMIT_EXCEEDED` (403) — the seat cap re-check found no room (`:76`).
152
- * Carries `feature`/`current`/`limit` alongside, unlike the others.
153
- *
154
- * ⚠️ Through 1.10.138 this union was `INVITE_INVALID | EMAIL_ALREADY_REGISTERED
155
- * | SEAT_LIMIT_REACHED | WEAK_PASSWORD` — four names sharing ZERO members with
156
- * what the handler emits, so a consumer switching on them matched nothing and
157
- * fell through to a generic error while compiling clean. This is a correction
158
- * of a contract that was never real, not a migration: nothing consumed the old
159
- * names.
160
- *
161
- * Not-found and real-but-expired deliberately collapse to the same 404 body as
162
- * `verify-invite`, so accept cannot be used as a finer-grained probe than the
163
- * pre-check already is.
164
- */
165
- type AcceptInviteErrorCode = 'VALIDATION_FAILED' | 'EMAIL_ALREADY_MEMBER' | 'INVITATION_NOT_FOUND' | 'INVITATION_NOT_PENDING' | 'INVALID_ROLE' | 'PLAN_LIMIT_EXCEEDED';
166
119
  /**
167
120
  * Success shape — acceptance logs the new user straight in, so this is a
168
121
  * full session payload rather than an acknowledgement.
@@ -633,97 +586,6 @@ declare global {
633
586
  unlinked: true;
634
587
  provider: CustomerSignInProvider;
635
588
  }
636
- /**
637
- * One active refresh-token family for an operator —
638
- * `stacks/lambdas/auth/_sessions.ts`, rows from `listSessions`.
639
- */
640
- interface OperatorSession {
641
- /** Rotation family — the refresh chain. Stable across refreshes of one login. */
642
- family: string;
643
- jti: string;
644
- /**
645
- * ⚠️ Unix SECONDS, not milliseconds — `createTokenRow` writes `nowSeconds()`.
646
- * The same `/auth` path carries MILLISECOND timestamps elsewhere
647
- * (`CustomerLoginAttempt.createdAt`), so the unit does not follow the route.
648
- */
649
- issuedAt: number;
650
- /** ⚠️ Unix SECONDS, like `issuedAt`. `issuedAt + ttlSeconds`. */
651
- expiresAt: number;
652
- userAgent?: string;
653
- ip?: string;
654
- /** ⚠️ Unix SECONDS. Present only under `includeRevoked=true`. */
655
- revokedAt?: number;
656
- /** The session making this very request. Exactly one row carries `true`. */
657
- current: boolean;
658
- /**
659
- * Device class, present only for non-browser sessions — today the Cloud
660
- * Print agent. Descriptive only; it exempts nothing from revocation, but it
661
- * lets a client warn that ending this session (or a blanket revoke-others)
662
- * also stops printing.
663
- */
664
- client?: 'printer';
665
- }
666
- /** `GET /auth?mode=sessions` body — `stacks/lambdas/auth/_sessions.ts`. */
667
- interface OperatorSessionsResponse {
668
- data: OperatorSession[];
669
- /**
670
- * ⚠️ `false` means the partition was capped and rows are MISSING. Do not
671
- * render the list as the user's full session list, and do not conclude a
672
- * device is absent because it is not in `data`.
673
- */
674
- complete: boolean;
675
- }
676
- /**
677
- * `POST /auth` mode `revoke-session` 200 body —
678
- * `stacks/lambdas/auth/_revokeSession.ts`.
679
- *
680
- * ⚠️ `logged_out_self` means the caller revoked their OWN session: the refresh
681
- * delivery is cleared in the same response, so the client must route to login
682
- * rather than continue. `revoked` echoes the `jti` that ended — it is an
683
- * identifier, never a count.
684
- */
685
- interface RevokeOperatorSessionResult {
686
- message: 'session_revoked' | 'logged_out_self';
687
- revoked: string;
688
- }
689
- /**
690
- * `POST /auth` mode `revoke-others` 200 body —
691
- * `stacks/lambdas/auth/_revokeOthers.ts`.
692
- *
693
- * ⚠️ `complete` is `true` on every 200 by construction: a partial sweep answers
694
- * `502 REVOKE_INCOMPLETE` instead, never a 200 carrying `complete: false`. So a
695
- * client must branch on the STATUS, not on this field.
696
- */
697
- interface RevokeOtherOperatorSessionsResult {
698
- message: 'others_revoked';
699
- revokedCount: number;
700
- complete: true;
701
- }
702
- /**
703
- * One operator login attempt — `GET /auth?mode=login-history` on the operator
704
- * host (`stacks/lambdas/auth/_loginHistory.ts`).
705
- *
706
- * ⚠️ Unlike the SESSION shapes above, this really IS the customer row, and the
707
- * alias is a name rather than a copy: both hosts call the one
708
- * `listLoginHistory` helper (`stacks/services/loginHistory.ts`) over one
709
- * `LoginAttemptRow`, differing only in the `kind` that builds the partition
710
- * key. So the two cannot drift apart while that helper is shared — and if it
711
- * ever stops being shared, this alias is the single place that has to change.
712
- *
713
- * It exists so an operator screen does not have to import a `Customer`-prefixed
714
- * type to describe an operator, which is what every consumer was doing.
715
- */
716
- type OperatorLoginAttempt = CustomerLoginAttempt;
717
- /**
718
- * `GET /auth?mode=login-history` body on the operator host. See
719
- * {@link OperatorLoginAttempt} for why this is an alias.
720
- *
721
- * ⚠️ `truncated: true` means rows are MISSING — INVERSE polarity to
722
- * `OperatorSessionsResponse.complete` on the sibling mode of the same route.
723
- * The rows a cap drops are the OLDEST in the window, so a partial trail
724
- * rendered as a complete one reads as "nothing happened before this".
725
- */
726
- type OperatorLoginHistoryResponse = CustomerLoginHistoryResponse;
727
589
  }
728
590
  /**
729
591
  * `body.error` codes the sign-in-method paths can refuse with.
package/dist/cart.d.ts CHANGED
@@ -35,7 +35,6 @@ declare global {
35
35
  status?: 'active' | 'abandoned' | 'converted' | 'parked';
36
36
  parkedBy?: string;
37
37
  parkedAt?: number;
38
- ttl?: number;
39
38
  version?: number;
40
39
  lines: CartLine[];
41
40
  /**
@@ -317,8 +316,6 @@ declare global {
317
316
  * error and both are redeemable.
318
317
  */
319
318
  interface Coupon {
320
- PK?: string;
321
- SK?: string;
322
319
  storeId: string;
323
320
  /** Normalized upper-case. The SK carries the same value. */
324
321
  code: string;
@@ -500,20 +497,6 @@ declare global {
500
497
  * race gets the same permanent answer either way.
501
498
  */
502
499
  type CouponRefusal = 'COUPON_NOT_FOUND' | 'COUPON_NOT_ACTIVE' | 'COUPON_EXPIRED' | 'COUPON_EXHAUSTED' | 'COUPON_EXHAUSTED_AT_CHECKOUT' | 'COUPON_MIN_SUBTOTAL' | 'COUPON_REQUIRES_CUSTOMER' | 'COUPON_BUDGET_EXHAUSTED' | 'COUPON_RATE_LIMITED' | 'COUPON_CURRENCY_MISMATCH';
503
- /**
504
- * The PHYSICAL key a cart was read from.
505
- *
506
- * ⚠️ Exists because a re-key makes a re-derived key silently wrong rather than
507
- * loudly wrong: DynamoDB's `Delete` on a key that does not exist SUCCEEDS, so a
508
- * writer that rebuilds `{ PK: BASKET#{storeId}, SK: customerId }` against a row
509
- * now living at `CART#{storeId}` / `{cartId}` completes, reports success, and
510
- * empties nothing. Carry this from the read and use it — never re-derive.
511
- */
512
- interface CartRef {
513
- PK: string;
514
- SK: string;
515
- legacy: boolean;
516
- }
517
500
  /**
518
501
  * The request body for every cart mutation, discriminated on `mode`.
519
502
  *
@@ -536,47 +519,6 @@ declare global {
536
519
  * - `merge.items` is `min(1).max(50)`.
537
520
  */
538
521
  type CartActionRequest = CartActionAddLine | CartActionChangeQuantity | CartActionRemoveLine | CartActionClear | CartActionMerge | CartActionSaveLine | CartActionRestoreLine | CartActionRemoveSavedLine | CartActionApplyCoupon | CartActionRemoveCoupon | CartActionSetLineDiscount;
539
- /**
540
- * WHICH cart an OPERATOR action acts on — the half of the operator request
541
- * that `CartActionRequest` cannot carry.
542
- *
543
- * The storefront takes the cart from the authenticated identity, so a
544
- * shopper's body names no target and `CartActionRequest` alone is complete
545
- * there. The operator surface acts on someone else's cart and must say which,
546
- * so `POST /baskets` refuses a body naming none of the three with
547
- * `400 CART_TARGET_REQUIRED`. A client typing an operator body as the bare
548
- * `CartActionRequest` therefore compiles and 400s on every write, which is
549
- * exactly what this type exists to stop.
550
- *
551
- * Modelled as a UNION rather than three optional fields so "at least one" is
552
- * enforced by `tsc` rather than discovered at runtime. Supplying more than one
553
- * is legal; the server resolves them in the order below.
554
- *
555
- * ⚠️ `cartId` is the ONLY one that reaches a WALK-IN ticket. Such a cart has
556
- * no `customerId` at all and the `PK-customerId` GSI is sparse, so no customer
557
- * lookup can find it by any route.
558
- */
559
- type OperatorCartTarget =
560
- /** That customer's own cart. */
561
- {
562
- customerId: string;
563
- cartId?: string;
564
- terminalId?: string;
565
- }
566
- /** One specific ticket, walk-ins included. */
567
- | {
568
- cartId: string;
569
- customerId?: string;
570
- terminalId?: string;
571
- }
572
- /** The till's currently OPEN ticket, minted if it has none. */
573
- | {
574
- terminalId: string;
575
- customerId?: string;
576
- cartId?: string;
577
- };
578
- /** The body `POST /baskets` accepts: any named action, plus a target. */
579
- type OperatorCartActionRequest = CartActionRequest & OperatorCartTarget;
580
522
  /**
581
523
  * Fields common to every action.
582
524
  *
package/dist/cjs/index.js CHANGED
@@ -83,5 +83,6 @@ __exportStar(require("./user.js"), exports);
83
83
  __exportStar(require("./userActivity.js"), exports);
84
84
  __exportStar(require("./valuation.js"), exports);
85
85
  __exportStar(require("./webhook.js"), exports);
86
+ __exportStar(require("./wire.js"), exports);
86
87
  __exportStar(require("./whatsapp.js"), exports);
87
88
  __exportStar(require("./provinces.js"), exports);
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /**
3
+ * The strip catalogues every wire boundary in the api runs on, published as
4
+ * runtime tuples.
5
+ *
6
+ * ⚠️ **The direction of the single-sourcing is forced, not chosen.** The
7
+ * obvious arrangement — declare each tuple next to the `delete` calls in
8
+ * `stacks/helpers/*.ts` and `import type` it from here — cannot compile: the
9
+ * published build (`contracts/tsconfig.build.json`) sets `rootDir: "./src"`,
10
+ * so any file this tree reaches outside `src` is a hard `TS6059`, and a build
11
+ * that did somehow reach it would emit api source into the npm package that
12
+ * `files: ["dist"]` exists to keep out. So the list lives HERE, where both
13
+ * sides can reach it, and the sanitisers build their `Set`s from it.
14
+ *
15
+ * The sanitisers keep their `ReadonlySet` shape at runtime — membership tests
16
+ * on a 9-key list run per row on hot read paths — but the MEMBERS come from
17
+ * these tuples, so a key added for the runtime strip is added to the type that
18
+ * describes the result in the same edit.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.ROW_TTL_KEYS = exports.USER_TOTP_INTERNAL_KEYS = exports.STORE_WHATSAPP_SECRET_KEYS = exports.STORE_MERCADOLIBRE_SECRET_KEYS = exports.STORE_GMAIL_SECRET_KEYS = exports.STORE_MP_SECRET_KEYS = exports.STORE_AFIP_SECRET_KEYS = exports.RESPONSE_STRIPPED_KEYS = void 0;
22
+ /**
23
+ * The seven keys `response()` deletes from `body.data`.
24
+ *
25
+ * ⚠️ Two levels, and NOT into arrays. `response()` strips the top-level object
26
+ * and each of its direct object-valued properties, so `data.totp.secretRef` is
27
+ * removed and `data.items[].hash` is NOT. {@link Wire} models exactly that,
28
+ * including the array hole — widening the runtime to descend into arrays is a
29
+ * behaviour change and would need its own change; a type that claimed the hole
30
+ * was closed would be strictly worse than one that documents it.
31
+ */
32
+ exports.RESPONSE_STRIPPED_KEYS = [
33
+ 'PK',
34
+ 'SK',
35
+ 'salt',
36
+ 'hash',
37
+ 'hashedToken',
38
+ 'secretRef',
39
+ 'pendingSecretRef',
40
+ ];
41
+ /**
42
+ * AFIP credentials on `Store.afip` / `Store.integrations.afip`. The cert and
43
+ * key PEMs plus every per-service WSAA ticket.
44
+ *
45
+ * ⚠️ The runtime strip also carries a PREFIX guard on `accessTicket*`, which no
46
+ * tuple can express — a ticket field added later is stripped at runtime but
47
+ * would still be declared on the type until it is listed here.
48
+ */
49
+ exports.STORE_AFIP_SECRET_KEYS = [
50
+ 'cert',
51
+ 'key',
52
+ 'accessTicket_EB',
53
+ 'accessTicket_RSF',
54
+ 'accessTicket_FEX',
55
+ 'accessTicket_FECRED',
56
+ 'accessTicket_CDC',
57
+ ];
58
+ /** MercadoPago OAuth credentials on `Store.mercadopago` / `Store.integrations.mercadopago`. */
59
+ exports.STORE_MP_SECRET_KEYS = ['accessToken', 'code', 'refreshToken'];
60
+ /** KMS-ciphertext Gmail OAuth credentials on `Store.integrations.gmail`. */
61
+ exports.STORE_GMAIL_SECRET_KEYS = ['refreshTokenEncrypted', 'accessTokenEncrypted'];
62
+ /** KMS-ciphertext Mercadolibre OAuth credentials + the single-flight refresh marker. */
63
+ exports.STORE_MERCADOLIBRE_SECRET_KEYS = [
64
+ 'accessTokenEncrypted',
65
+ 'refreshTokenEncrypted',
66
+ 'refreshAttemptAt',
67
+ ];
68
+ /** WhatsApp's only secret field on `Store.integrations.whatsapp`. */
69
+ exports.STORE_WHATSAPP_SECRET_KEYS = ['accessToken'];
70
+ /**
71
+ * The TOTP sub-keys `sanitizeUserRow` drops from `User.totp` before a USER row
72
+ * crosses any wire.
73
+ *
74
+ * ⚠️ `recoveryCodes` is on this list and `response()` structurally cannot cover
75
+ * it: the stored form is an ARRAY of `{ hash, usedAt }`, and `response()`'s
76
+ * nested sweep skips arrays. The strip has to happen at the row source.
77
+ */
78
+ exports.USER_TOTP_INTERNAL_KEYS = [
79
+ 'secretRef',
80
+ 'pendingSecretRef',
81
+ 'recoveryCodes',
82
+ 'recoveryCodesGeneratedAt',
83
+ 'lastCounter',
84
+ 'lastUsedAt',
85
+ 'pendingAt',
86
+ 'failedAttempts',
87
+ 'lockedUntil',
88
+ ];
89
+ /**
90
+ * The DynamoDB housekeeping attribute that is stored on a row and must not be
91
+ * echoed back on a read of it.
92
+ *
93
+ * ⚠️ **"Storage-only" is a property of (entity, field), never of the bare
94
+ * name.** `CustomerLoginAttempt.ttl` is deliberately wire-visible — the login
95
+ * history renders it — so this list is applied PER ENTITY at the handlers that
96
+ * project a stored row, and is never folded into {@link RESPONSE_STRIPPED_KEYS},
97
+ * which would un-publish a field a consumer already reads.
98
+ */
99
+ exports.ROW_TTL_KEYS = ['ttl'];
@@ -171,8 +171,6 @@ declare global {
171
171
  appleRelayEmail?: string;
172
172
  favorites?: Partial<Product>[];
173
173
  fullName: string;
174
- /** Storage-only credential hash — stripped from every response by the api's central sanitizer; never present on reads. */
175
- hash?: string;
176
174
  lastBuy?: number;
177
175
  lastLog?: number;
178
176
  /**
@@ -258,8 +256,6 @@ declare global {
258
256
  */
259
257
  priceList: number;
260
258
  province: string;
261
- /** Storage-only credential salt — stripped from every response by the api's central sanitizer; never present on reads. */
262
- salt?: string;
263
259
  /**
264
260
  * @deprecated Lowercase WRITE-SIDE index for backend `contains` filtering.
265
261
  * Internal — not part of the read contract, even where legacy responses
@@ -18,103 +18,5 @@ declare global {
18
18
  * cannot do.
19
19
  */
20
20
  type CycleCountStatus = 'open' | 'finalized' | 'cancelled';
21
- /**
22
- * A physical count session that the SERVER owns — an id, a stored line set,
23
- * and a read path. It exists because a stocktake has been a purely
24
- * client-side construct: the count lived in one browser, no id was minted,
25
- * nothing indexed it, and a session lost mid-count was simply gone.
26
- *
27
- * ⚠️ **`cycleCountId` IS the value written into `stocktakeId` on the movement
28
- * rows** this session emits when it finalises. That field was published ahead
29
- * of this entity precisely so the two would meet without a backfill, and it
30
- * constrains what a legal id looks like: 1–64 characters of `[A-Za-z0-9_-]`.
31
- * Minting an id outside that charset silently orphans every adjustment the
32
- * session produces, because the grouping field will not accept it and this
33
- * platform is forward-only.
34
- *
35
- * ⚠️ **A count is not a lock.** Nothing freezes stock while the session is
36
- * open: sales keep depleting and receipts keep adding, so a variance computed
37
- * from a `systemQuantity` captured minutes earlier attributes real trade to
38
- * miscounting. The longer a session stays `open`, the more of its variance is
39
- * legitimate movement. That is inherent, not a defect to design around here —
40
- * but a consumer must not present the variance as shrinkage.
41
- */
42
- interface CycleCount {
43
- storeId: string;
44
- /** Server-minted. ⚠️ Must satisfy the `stocktakeId` charset — see the interface note. */
45
- cycleCountId: string;
46
- /** Unix ms the session was opened. */
47
- createdAt: number;
48
- updatedAt?: number;
49
- /** The operator who opened it. */
50
- userId: string;
51
- status: CycleCountStatus;
52
- /** The `YYYYMMDD` day the count was taken. */
53
- dated: number;
54
- /**
55
- * Operator-facing label for the session ("Depósito, estante 3"). Prose, for
56
- * a human reading a list of past counts; nothing derives from it.
57
- */
58
- name?: string;
59
- /**
60
- * The `Product.zone` this session was scoped to, when it was scoped at all.
61
- *
62
- * ⚠️ Descriptive, not a guarantee. It records what the operator SAID they
63
- * were counting; nothing forces every line to belong to that zone, and
64
- * nothing forces every product in that zone to appear. A zoned session is
65
- * not evidence that the zone was counted completely.
66
- */
67
- zone?: string;
68
- items: CycleCountItem[];
69
- /** Unix ms the variances were applied. Present only on a `finalized` session. */
70
- finalizedAt?: number;
71
- /** The operator who applied them — not necessarily the one who opened the session. */
72
- finalizedBy?: string;
73
- /** Operator note. ⚠️ Never personal data — this row is not scrubbed and has no TTL. */
74
- notes?: string;
75
- /** Lowercase '#'-joined write-side index. Internal; not part of the read contract. */
76
- search?: string;
77
- disabled?: boolean;
78
- }
79
- /**
80
- * One counted product.
81
- *
82
- * A line whose `countedQuantity` equals its `systemQuantity` still belongs in
83
- * the session: "we looked and it was right" is the evidence a count exists to
84
- * produce, and dropping matching lines makes a completed count
85
- * indistinguishable from an abandoned one.
86
- */
87
- interface CycleCountItem {
88
- productId: string;
89
- /** Name and SKU DENORMALIZED at count time, so a later catalogue rename does not rewrite history. */
90
- name?: string;
91
- sku?: string;
92
- /**
93
- * On-hand as the SYSTEM believed it at the moment this line was captured —
94
- * a snapshot, stored rather than recomputed at finalise.
95
- *
96
- * ⚠️ It is stored precisely so the variance stays reproducible. Recomputing
97
- * it at finalise would make the applied adjustment disagree with the number
98
- * the operator was shown while counting, and the operator's number is the
99
- * one they signed off.
100
- */
101
- systemQuantity: number;
102
- /** What the operator physically counted. */
103
- countedQuantity: number;
104
- /**
105
- * The batch counted, when the product is lot-tracked.
106
- *
107
- * ⚠️ Optional even on a lot-tracked product, because a real count often
108
- * cannot attribute units to a batch — mixed shelf stock, a rubbed-off
109
- * carton code. Absence means "counted, batch unknown", never "not
110
- * lot-tracked", so an adjustment from such a line depletes the product
111
- * without depleting any lot.
112
- */
113
- lotId?: string;
114
- /** Why the line differs. ⚠️ Never personal data — it rides into an un-scrubbed, TTL-less row. */
115
- note?: string;
116
- /** Unix ms this line was captured. Its distance from `finalizedAt` is how stale `systemQuantity` is. */
117
- countedAt?: number;
118
- }
119
21
  }
120
22
  export {};
@@ -109,22 +109,5 @@ declare global {
109
109
  /** Set only on a `'failed'` event. */
110
110
  failureReason?: DeliveryFailureReason;
111
111
  }
112
- /**
113
- * A `DeliveryProofAsset` carrying the read-time-only `downloadUrl` minted by
114
- * `withDeliveryProofDownloadUrls` (`stacks/services/deliveryAttachments.ts`)
115
- * and served by `stacks/lambdas/deliveries/_get.ts`.
116
- *
117
- * ⚠️ Ephemeral and never persisted — a presigned S3 GET, minted fresh on every
118
- * read. A client that caches it past its TTL gets a 403 from S3, not from the
119
- * api, so the failure does not look like an api error. Never send it back on a
120
- * write.
121
- */
122
- type DeliveryProofAssetWithUrl = DeliveryProofAsset & {
123
- downloadUrl: string;
124
- };
125
- /** `DeliveryEvent` with a resolved `proof[]` — see {@link DeliveryProofAssetWithUrl}. */
126
- type DeliveryEventWithProofUrls = Omit<DeliveryEvent, 'proof'> & {
127
- proof?: DeliveryProofAssetWithUrl[];
128
- };
129
112
  }
130
113
  export {};
package/dist/demo.d.ts CHANGED
@@ -6,16 +6,5 @@
6
6
  * enforced server-side via the `requireWritable` gate (ADR-0010);
7
7
  * see also `Store.type === 'demo'` in store.ts.
8
8
  */
9
- declare global {
10
- /**
11
- * Firebase custom claims attached to a demo session token; `demo: true`
12
- * marks the session as a demo tenant.
13
- */
14
- interface DemoClaims {
15
- demo: true;
16
- storeId: string;
17
- /** When true, all writes are blocked (view-only demo). */
18
- readOnly: boolean;
19
- }
20
- }
9
+ declare global { }
21
10
  export {};
package/dist/imports.d.ts CHANGED
@@ -1,22 +1,4 @@
1
1
  declare global {
2
- interface ProductSale {
3
- pk: string;
4
- sk: string;
5
- orderId: string;
6
- customerId: string;
7
- fullName: string;
8
- quantity: number;
9
- price: number;
10
- }
11
- interface ProductIncome {
12
- pk: string;
13
- sk: string;
14
- orderId?: string;
15
- supplierId: string;
16
- supplierName?: string;
17
- quantity: number;
18
- cost: number;
19
- }
20
2
  /**
21
3
  * Envelope returned by the bulk CSV import endpoints — `POST /products` and
22
4
  * `POST /customers` with `mode: 'import'`.
package/dist/index.d.ts CHANGED
@@ -59,5 +59,6 @@ export * from './user.ts';
59
59
  export * from './userActivity.ts';
60
60
  export * from './valuation.ts';
61
61
  export * from './webhook.ts';
62
+ export * from './wire.ts';
62
63
  export * from './whatsapp.ts';
63
64
  export * from './provinces.ts';
package/dist/index.js CHANGED
@@ -67,5 +67,6 @@ export * from "./user.js";
67
67
  export * from "./userActivity.js";
68
68
  export * from "./valuation.js";
69
69
  export * from "./webhook.js";
70
+ export * from "./wire.js";
70
71
  export * from "./whatsapp.js";
71
72
  export * from "./provinces.js";