ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+161
View File
@@ -0,0 +1,161 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// Simulated ports cover contract/app rules; real service fiscal transactions are separate acceptance.
import { describe, expect, it, vi } from "vitest"
import { decimal, draft, invoiceTerms, issue, revision } from "../contract/index.js"
import { transitionInvoice, updateDraft, validateTerms } from "../core/invoices.js"
import { type InvoicingService, readsOf } from "../core/ports.js"
import { en } from "../i18n/en.js"
import { lt } from "../i18n/lt.js"
import { draftData } from "../ui/form-data.js"
import { id, invoiceId, row, terms } from "./fixture.js"
function service(): InvoicingService {
return {
list: vi.fn(async () => ({ rows: [row] })),
get: vi.fn(async () => row),
series: vi.fn(async () => ({ rows: [] })),
ubl: vi.fn(async () => ({ filename: "fixture.xml", xml: "<Invoice/>" })),
draft: vi.fn(async () => row),
update: vi.fn(async () => row),
transition: vi.fn(async () => row),
createSeries: vi.fn(async () => {
throw new Error("not in this fixture")
}),
}
}
describe("Invoicing contracts and safe app operations", () => {
it("keeps amounts exact and rejects number/exponent and malformed integer inputs without throwing", () => {
expect(invoiceTerms.parse(terms).lines[0]?.net_price.amount).toBe("9007199254740993.123456789012345678")
for (const bad of [1, NaN, Infinity, "1e3", "1.2.3", ""]) expect(decimal.safeParse(bad).success).toBe(false)
for (const bad of ["oops", "1.5", "9223372036854775808", ""]) expect(revision.safeParse(bad).success).toBe(false)
expect(
draft.input.safeParse({
org: "fixture",
data: { ...terms, lines: [{ ...terms.lines[0], quantity: "oops" }] },
requestId: id,
}).success,
).toBe(false)
})
it("refuses cross-currency terms before an external mutation", () => {
expect(() =>
validateTerms({
...terms,
lines: [
{
...terms.lines[0],
quantity: "2",
item_name: "Synthetic",
unit: "C62",
vat_category: "S",
net_price: { currency: "USD", amount: "1" },
},
],
}),
).toThrow()
})
it("requires an explicit confirmation and grants no write methods to a read view", async () => {
expect(
issue.input.safeParse({ org: "fixture", invoiceId, expectedVersion: "1", requestId: id, confirmed: false })
.success,
).toBe(false)
const port = service()
expect("draft" in readsOf(port)).toBe(false)
await expect(
transitionInvoice(port, "issue", { invoiceId, expectedVersion: "1", requestId: id, confirmed: false as never }),
).rejects.toMatchObject({ code: "bad_request" })
expect(port.transition).not.toHaveBeenCalled()
})
it("forwards the same exact revision and idempotency key on response-loss retries", async () => {
const port = service()
const input = { invoiceId, expectedVersion: "1", requestId: id, confirmed: true as const }
await transitionInvoice(port, "issue", input)
await transitionInvoice(port, "issue", input)
expect(vi.mocked(port.transition).mock.calls[0]).toEqual(vi.mocked(port.transition).mock.calls[1])
expect(port.transition).toHaveBeenCalledWith(
"issue",
expect.objectContaining({ expectedVersion: "1", key: `invoicing:issue:${id}` }),
)
})
it("does not predict a future revision, and delegates stale receipt resolution to the service", async () => {
const port = service()
await expect(
updateDraft(port, { invoiceId, data: terms, expectedVersion: "9007199254740994", requestId: id }),
).rejects.toMatchObject({ code: "conflict" })
expect(port.update).not.toHaveBeenCalled()
await updateDraft(port, { invoiceId, data: terms, expectedVersion: "1", requestId: id })
expect(port.update).toHaveBeenCalledWith(invoiceId, terms, "1", `invoicing:update:${id}`)
})
it("retains unedited invoice terms and exact digits while editing an existing draft", () => {
const prior = {
...terms,
notes: ["Synthetic note"],
ext: { fixture: "retain" },
payment_means: { code: "30", account_id: "SYNTHETIC" },
seller: { ...terms.seller, trading_name: "Synthetic trading" },
}
const values: Record<string, string> = {
series: terms.series_id,
currency: terms.currency,
issueDate: terms.issue_date,
buyerReference: terms.buyer_reference,
}
for (const side of ["seller", "buyer"] as const) {
const party = terms[side]
Object.assign(values, {
[`${side}.reference`]: party.reference,
[`${side}.name`]: party.name,
[`${side}.country`]: party.address.country,
[`${side}.scheme`]: party.endpoint.scheme,
[`${side}.endpoint`]: party.endpoint.value,
[`${side}.vatScheme`]: party.vat_identifier?.scheme ?? "vat",
[`${side}.vatValue`]: party.vat_identifier?.value ?? "",
})
}
const line = terms.lines[0]
if (!line) throw new Error("fixture line absent")
Object.assign(values, {
"line.0.name": line.item_name,
"line.0.quantity": line.quantity,
"line.0.unit": line.unit,
"line.0.price": line.net_price.amount,
"line.0.category": line.vat_category,
"line.0.rate": line.vat_rate ?? "",
})
const next = draftData(values, 1, "en", prior)
expect(next.ext).toEqual(prior.ext)
expect(next.payment_means).toEqual(prior.payment_means)
expect(next.seller.trading_name).toBe(prior.seller.trading_name)
expect(next.notes).toEqual(prior.notes)
expect(next.lines[0]?.net_price.amount).toBe(line.net_price.amount)
})
it("reads a price and a VAT rate as a Lithuanian reader types them, exactly", () => {
const values: Record<string, string> = {
series: terms.series_id,
currency: "EUR",
issueDate: terms.issue_date,
buyerReference: terms.buyer_reference,
"line.0.name": "Varžtas",
"line.0.quantity": "3",
"line.0.unit": "H87",
"line.0.price": "1\u00a0234,50",
"line.0.category": "S",
"line.0.rate": "21",
}
for (const side of ["seller", "buyer"] as const) {
const party = terms[side]
Object.assign(values, {
[`${side}.reference`]: party.reference,
[`${side}.name`]: party.name,
[`${side}.scheme`]: party.endpoint.scheme,
[`${side}.endpoint`]: party.endpoint.value,
[`${side}.country`]: party.address.country,
})
}
const next = draftData(values, 1, "lt", terms)
expect(next.lines[0]?.net_price).toEqual({ currency: "EUR", amount: "1234.50" })
expect(next.lines[0]?.vat_rate).toBe("21")
expect(() => draftData({ ...values, "line.0.price": "12,5,0" }, 1, "lt", terms)).toThrow()
})
it("ships the same translated labels in both languages", () =>
expect(Object.keys(en).sort()).toEqual(Object.keys(lt).sort()))
})
+71
View File
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
import type { InvoiceTerms, InvoiceView } from "../contract/index.js"
export const id = "01900000-0000-7000-8000-000000000001"
export const invoiceId = `inv_${id}`
export const seriesId = `ser_${id}`
export const terms: InvoiceTerms = {
type_code: "380",
series_id: seriesId,
issue_date: "2026-11-03",
currency: "EUR",
buyer_reference: "Synthetic-order",
seller: {
reference: `conusai://crm/parties/pty_${id}`,
name: "Synthetic Seller",
vat_identifier: { scheme: "vat", value: "LT100000001" },
endpoint: { scheme: "0088", value: "1234567890128" },
address: { country: "LT", city: "Synthetic city" },
},
buyer: {
reference: `conusai://crm/parties/pty_${id}`,
name: "Synthetic Buyer",
endpoint: { scheme: "0088", value: "1234567890128" },
address: { country: "LT" },
},
lines: [
{
item_name: "Synthetic item",
quantity: "2",
unit: "C62",
net_price: { currency: "EUR", amount: "9007199254740993.123456789012345678" },
vat_category: "S",
vat_rate: "21",
},
],
}
export const row: InvoiceView = {
invoiceId,
revision: "9007199254740993",
status: "draft",
number: null,
data: terms,
payable: { currency: "EUR", amount: "18014398509481986.246913578024691356" },
deleted: false,
erased: false,
}
export const raw = () => ({
id: invoiceId,
revision: "RAW_REVISION",
status: "draft",
number: null,
data: { ...terms, lines: terms.lines.map((line) => ({ ...line, quantity: 2 })) },
calculated: {
line_nets: [],
totals: Object.fromEntries(
[
"allowance",
"charge",
"line_extension",
"payable",
"prepaid",
"rounding",
"tax",
"tax_exclusive",
"tax_inclusive",
].map((key) => [key, row.payable]),
),
vat_breakdown: [],
},
deleted: false,
erased: false,
})
+30
View File
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
import type { TransportCaller } from "@conusai-kit/core"
import type { IsolationFixture, IsolationTenant } from "@conusai-kit/testing"
import { businessModulesOn } from "../../index.js"
import { id, invoiceId, seriesId, terms } from "./fixture.js"
const org = (t: IsolationTenant) => ({ org: t.orgSlug })
const get = (t: IsolationTenant) => ({ ...org(t), invoiceId })
const action = (t: IsolationTenant) => ({ ...get(t), expectedVersion: "1", requestId: id, confirmed: true })
export const invoicingIsolationFixtures: Record<string, IsolationFixture> = {
"invoicing.invoice.list": { input: org },
"invoicing.series.list": { input: org },
"invoicing.invoice.get": { input: get },
"invoicing.invoice.ubl": { input: get },
"invoicing.invoice.draft": { input: (t) => ({ ...org(t), data: terms, requestId: id }) },
"invoicing.invoice.update": { input: (t) => ({ ...action(t), data: terms }) },
"invoicing.invoice.issue": { input: action },
"invoicing.invoice.credit": { input: (t) => ({ ...action(t), seriesId, reason: "Synthetic correction" }) },
"invoicing.invoice.void": { input: (t) => ({ ...action(t), reason: "Synthetic correction" }) },
"invoicing.series.create": {
input: (t) => ({ ...org(t), code: "SYNTH", prefix: "SYNTH-", kind: "invoice", requestId: id }),
},
}
export const isolation: {
seed(
call: TransportCaller,
inProject: { org: string; workspace: string; project: string },
): Promise<Record<string, string>>
fixtures: Record<string, IsolationFixture>
} = { seed: async () => ({}), fixtures: businessModulesOn.includes("invoicing") ? invoicingIsolationFixtures : {} }
+36
View File
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// The invoice terms accept exactly what the Invoicing service accepts: its `DecimalAmount` grammar and ISO 4217
// codes (business-services/types). The module's own regex let `007.50` and `XYZ` through, which the service then
// refused; a person found out only after submitting.
import { describe, expect, it } from "vitest"
import { decimal, line, money } from "../contract/index.js"
describe("the invoice's exact money", () => {
it("refuses an amount with a leading zero and a currency the service does not know", () => {
for (const amount of ["007.50", "00", "-01", "1.", ".5", "+1", "1e3", "1,50"]) {
expect(decimal.safeParse(amount).success, amount).toBe(false)
}
expect(money.safeParse({ amount: "7.50", currency: "XYZ" }).success).toBe(false)
expect(money.safeParse({ amount: "7.50", currency: "LTL" }).success).toBe(false)
})
it("takes a line's unit only as a UN/CEFACT Rec 20 code the service accepts", () => {
const base = {
quantity: "3",
item_name: "Bolt",
net_price: { amount: "1.20", currency: "EUR" },
vat_category: "S",
vat_rate: "21",
}
expect(line.safeParse({ ...base, unit: "C62" }).success).toBe(true)
for (const unit of ["pcs", "PCS", "XBX", "m2"]) expect(line.safeParse({ ...base, unit }).success, unit).toBe(false)
})
it("accepts every amount the service accepts, trailing zeros and its bounds included", () => {
for (const amount of ["0", "-0.00", "7.50", "9999999999999999999999999999.999999999999999999"]) {
expect(decimal.safeParse(amount).success, amount).toBe(true)
}
expect(decimal.safeParse("10000000000000000000000000000").success).toBe(false)
expect(money.safeParse({ amount: "7.50", currency: "EUR" }).success).toBe(true)
})
})
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// Memory app + injected service port. Proves app membership/roles, never external partition isolation.
import { type Actor, buildRegistry, Container, createCaller } from "@conusai-kit/core"
import { createMemoryDataSource, DATA_SOURCE, entitiesOf, SYSTEM_DATA } from "@conusai-kit/data"
import { createTenancyHooks, TENANCY, tenancyModule, users } from "@conusai-kit/tenancy"
import { describe, expect, it, vi } from "vitest"
import { simulatedBusinessAdmission } from "../../../test/helpers/business-admission.js"
import { INVOICING_SERVICE, type InvoicingService } from "../core/ports.js"
import { invoicingModule } from "../module.js"
import { id, invoiceId, row, terms } from "./fixture.js"
import { invoicingIsolationFixtures } from "./isolation.js"
async function fixture() {
const registry = buildRegistry([tenancyModule, invoicingModule])
const data = createMemoryDataSource({ entities: entitiesOf(registry, "postgres") })
const root = new Container()
root.value(DATA_SOURCE, data)
root.value(SYSTEM_DATA, data)
const port: InvoicingService = {
list: vi.fn(async () => ({ rows: [row] })),
get: vi.fn(async () => row),
series: vi.fn(async () => ({ rows: [] })),
ubl: vi.fn(async () => ({ filename: "fixture.xml", xml: "<Invoice/>" })),
draft: vi.fn(async () => row),
update: vi.fn(async () => row),
transition: vi.fn(async () => row),
createSeries: vi.fn(async () => {
throw new Error("not used")
}),
}
root.value(INVOICING_SERVICE, port)
const caller = (actor: Actor) => {
const tenancy = createTenancyHooks({ data, registry })
const container = root.child()
container.value(TENANCY, tenancy)
return createCaller({ registry, container, tenancy, serviceReadiness: simulatedBusinessAdmission }, { actor })
}
const user = async (name: string) => {
const row = await data.global(users).insert({
issuer: "https://id.example.test",
subject: name,
email: `${name}@example.test`,
displayName: name,
locale: "en",
})
return { userId: row.id }
}
const owner = caller(await user("owner"))
await owner.callByName("tenancy.org.create", { slug: "alpha", name: "Synthetic Alpha" })
const foreign = caller(await user("foreign"))
await foreign.callByName("tenancy.org.create", { slug: "beta", name: "Synthetic Beta" })
const invite = (await owner.callByName("tenancy.member.invite", {
org: "alpha",
email: "viewer@example.test",
role: "viewer",
})) as { token: string }
const viewer = caller(await user("viewer"))
await viewer.callByName("tenancy.invitation.accept", { org: "alpha", token: invite.token })
return { owner, foreign, viewer, port }
}
describe("Invoicing app dispatch (simulated service)", () => {
it("denies every foreign-organization operation before reaching a service port", async () => {
const { owner, port } = await fixture()
for (const [name, fixture] of Object.entries(invoicingIsolationFixtures)) {
const input = fixture.input({ orgSlug: "beta" } as never)
await expect(owner.callByName(name, input)).rejects.toMatchObject({ code: "not_found" })
}
for (const method of Object.values(port)) expect(method).not.toHaveBeenCalled()
})
it("allows viewer reads but refuses fiscal writes and series administration", async () => {
const { viewer, port } = await fixture()
expect(await viewer.callByName("invoicing.invoice.list", { org: "alpha" })).toMatchObject({ rows: [{ invoiceId }] })
for (const name of [
"invoicing.invoice.draft",
"invoicing.invoice.update",
"invoicing.invoice.issue",
"invoicing.invoice.credit",
"invoicing.invoice.void",
"invoicing.series.create",
]) {
const fixture = invoicingIsolationFixtures[name]
if (!fixture) throw new Error("fixture missing")
await expect(viewer.callByName(name, fixture.input({ orgSlug: "alpha" } as never))).rejects.toMatchObject({
code: "not_found",
})
}
expect(port.draft).not.toHaveBeenCalled()
expect(port.transition).not.toHaveBeenCalled()
expect(port.createSeries).not.toHaveBeenCalled()
})
it("routes an authorized draft with exact strings and a stable operation key", async () => {
const { owner, port } = await fixture()
const result = await owner.callByName("invoicing.invoice.draft", { org: "alpha", data: terms, requestId: id })
expect(result).toMatchObject({ invoiceId, revision: row.revision })
expect(port.draft).toHaveBeenCalledWith(terms, `invoicing:draft:${id}`)
})
})
+114
View File
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// Actual generated SDK over synthetic HTTP; this is not live fiscal/provider acceptance.
import { requestBusinessBinding } from "@conusai-kit/business"
import { businessServiceHooks } from "@conusai-kit/business/server"
import { Container, type ServiceAdmissionContext } from "@conusai-kit/core"
import { afterEach, describe, expect, it, vi } from "vitest"
import { sdkInvoicingService } from "../adapters/service.js"
import { invoicingModule } from "../module.js"
import { id, invoiceId, raw, terms } from "./fixture.js"
const bindingId = id
function json(value: unknown) {
return new Response(JSON.stringify(value).replaceAll('"RAW_REVISION"', "9007199254740993"), {
headers: { "content-type": "application/json" },
})
}
async function fixture(reply: (request: Request) => Response | Promise<Response>) {
const requests: Request[] = []
vi.stubGlobal("fetch", async (input: Request | string | URL) => {
const request = new Request(input)
requests.push(request.clone())
return reply(request)
})
const container = new Container()
const hooks = businessServiceHooks({
env: { apiUrl: "https://platform.example.test/api", token: "synthetic-token", orgSlug: "fixture" },
platformOrganizationId: 7,
platformProjectId: 9,
platformEnvironmentId: 11,
profile: "postgres",
controlPlane: {
lookup: async (appTenantId) => ({
partition_major: 1,
binding_id: bindingId,
organization_id: 7,
project_id: 9,
environment_id: 11,
environment_uuid: id,
app_tenant_id: appTenantId,
}),
observe: async () => {
throw new Error("This fixture does not certify readiness")
},
},
})
const context: ServiceAdmissionContext = {
container,
module: "invoicing",
procedure: "invoicing.invoice.list",
kind: "read",
scope: { level: "org", orgId: id, actor: { userId: id } },
}
await hooks.prepareServices?.(container, context, invoicingModule.serviceRequirements ?? [])
return { service: sdkInvoicingService(requestBusinessBinding(container)), requests }
}
afterEach(() => vi.unstubAllGlobals())
describe("Invoicing generated wire adapter", () => {
it("preserves decimal and int64 digits through a real generated client", async () => {
const { service, requests } = await fixture(() => json(raw()))
const result = await service.get(invoiceId)
expect(result.revision).toBe("9007199254740993")
expect(result.data.lines[0]?.net_price.amount).toBe(terms.lines[0]?.net_price.amount)
await service.transition("issue", { invoiceId, expectedVersion: result.revision, key: `fixture:${id}` })
const body = await requests[1]?.text()
expect(body).toContain('"revision":9007199254740993')
expect(body).toContain(`fixture:${id}`)
})
it("denies a foreign app subject before issuing any network request", async () => {
const { service, requests } = await fixture(() => json(raw()))
await expect(
service.draft(
{
...terms,
buyer: {
...terms.buyer,
reference:
"conusai://app-partitions/01900000-0000-7000-8000-000000000099/members/01900000-0000-7000-8000-000000000001",
},
},
`fixture:${id}`,
),
).rejects.toMatchObject({ code: "bad_request" })
expect(requests).toHaveLength(0)
})
it("returns bounded XML for explicit download instead of parsing it as JSON", async () => {
const { service } = await fixture(
() => new Response("<Invoice>synthetic</Invoice>", { headers: { "content-type": "application/xml" } }),
)
expect(await service.ubl(invoiceId)).toEqual({
filename: `invoice-${invoiceId}.xml`,
xml: "<Invoice>synthetic</Invoice>",
})
})
it("maps service failures without returning arbitrary private remote details", async () => {
const { service } = await fixture(
() =>
new Response(
JSON.stringify({
type: "https://conusai.com/problems/conflict",
title: "Conflict",
status: 409,
detail: "private fixture value",
}),
{ status: 409, headers: { "content-type": "application/problem+json" } },
),
)
const refused = await service.get(invoiceId).then(
() => undefined,
(error: unknown) => error,
)
expect(refused).toMatchObject({ code: "business_conflict", status: 409 })
expect(JSON.stringify((refused as { problem: unknown }).problem)).not.toContain("private fixture value")
})
})