Clean prepaid SoT, identity mailbox, public access planes, leaf policy, fleet spawn
Some checks are pending
offline / test (push) Waiting to run

Persist account-balance books; edge caches prepaid from books. Add zappier-identity, verae-nats-accounts, verae-jobs-events, verae-access-staff, zapier-decisions. Edge binds loopback; lan-134 stays off; HTTP services prefer local spawn.
This commit is contained in:
George Lambert 2026-09-11 17:15:16 -04:00
parent 345aeeead9
commit ddf772454b
153 changed files with 2236 additions and 116 deletions

View file

@ -0,0 +1,50 @@
/**
* Prepaid mutations. Account-balance is the writer when NATS or HTTP books exist.
* Tests (no NATS_URL, no ACCOUNT_BALANCE_URL) keep a local cache only.
*/
import { natsAdjust, natsStatement } from './billing-nats';
import type { AccessPlane } from './billing-nats';
export type PrepaidRow = {
customerId: string;
veraeUserId?: string;
cents: number;
reason: string;
agent: string;
kind?: string;
prepaidCents?: number;
};
function booksUrl(): string {
return (process.env.ACCOUNT_BALANCE_URL || '').replace(/\/$/, '');
}
export function booksConfigured(): boolean {
return Boolean(process.env.NATS_URL || booksUrl());
}
export async function ledgerAdjust(row: PrepaidRow, plane: AccessPlane): Promise<PrepaidRow | null> {
const viaNats = await natsAdjust(row, plane);
if (viaNats && typeof viaNats === 'object' && viaNats !== null && 'prepaidCents' in viaNats) {
return viaNats as PrepaidRow;
}
const base = booksUrl();
if (!base) return null;
const r = await fetch(`${base}/adjust`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(row),
});
if (!r.ok) return null;
return (await r.json()) as PrepaidRow;
}
export async function ledgerStatement(customerId: string, plane: AccessPlane, veraeUserId?: string) {
const nats = await natsStatement(customerId, plane, veraeUserId);
if (nats) return nats;
const base = booksUrl();
if (!base) return null;
const r = await fetch(`${base}/statement/${encodeURIComponent(customerId)}`);
if (!r.ok) return null;
return r.json();
}