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
+26
View File
@@ -0,0 +1,26 @@
// The module's names, in a file with no import: a browser bundle can take them without the schemas.
/** The platform service this module is a client of (B-wave contract §3.14). */
export const CRM_SERVICE_NAME = "crm"
/** The app permissions of the module. */
export const CRM_PERMISSIONS = {
read: "crm.party.read",
write: "crm.party.write",
} as const
/**
* The identifier scheme that links a party to one of this app's people: its value is the person's
* partition-bound member reference (`actorRef` of @conusai-kit/business), which an export or an erasure of that
* person through the platform reaches (B-wave contract §3.8).
*/
export const SUBJECT_SCHEME = "conusai.subject"
/** The contact kinds the module's form adds; the service keeps postal addresses and Peppol endpoints too. */
export const CONTACT_KINDS = ["email", "phone", "web"] as const
/** What a contact point is for, as the service names it. */
export const CONTACT_PURPOSES = ["billing", "delivery", "invoice_email", "site"] as const
/** The most rows one page of a list asks the service for. */
export const PAGE_LIMIT = 50
+21
View File
@@ -0,0 +1,21 @@
// The public API of the crm module: what a page, another module and the OpenAPI document may import.
// Nothing here reaches core/, adapters/ or a service client.
export {
CONTACT_KINDS,
CONTACT_PURPOSES,
CRM_PERMISSIONS,
CRM_SERVICE_NAME,
PAGE_LIMIT,
SUBJECT_SCHEME,
} from "./constants.js"
export {
type ContactView,
contactAdd,
contactViewSchema,
type PartyView,
partyCreate,
partyGet,
partyList,
partyViewSchema,
} from "./procedures.js"
+101
View File
@@ -0,0 +1,101 @@
// The procedure contracts of the crm module: schemas and names, no handler and no port.
//
// The module is a client of the platform's CRM service (B-wave contract §3.14): parties and their
// contact points live there, in the deployment's organization, and every procedure is one or two
// service calls. A read reads; a change is an `effect` (it calls an external service and writes
// nothing of this app's own).
import { procedure } from "@conusai-kit/core"
import { z } from "zod"
import { CONTACT_KINDS, CONTACT_PURPOSES, CRM_PERMISSIONS } from "./constants.js"
const inProject = { org: z.string(), workspace: z.string(), project: z.string() }
/** What a form generates once per submission, so a retried request creates once. */
const requestId = z.string().uuid()
const partyId = z.string().min(1).max(64)
export const partyViewSchema = z.object({
partyId: z.string(),
kind: z.enum(["person", "organization"]),
displayName: z.string(),
legalName: z.string().nullable(),
/** ISO 3166-1 alpha-2. */
country: z.string(),
status: z.enum(["active", "archived", "merged"]),
/** Whether an identifier links the party to one of this app's people. */
linked: z.boolean(),
})
export type PartyView = z.output<typeof partyViewSchema>
export const contactViewSchema = z.object({
contactId: z.string(),
kind: z.enum(["postal", "email", "phone", "web", "peppol_endpoint"]),
/** The value as a person reads it; empty once the service erased it. */
value: z.string(),
purposes: z.array(z.enum(CONTACT_PURPOSES)),
isPrimary: z.boolean(),
erased: z.boolean(),
})
export type ContactView = z.output<typeof contactViewSchema>
export const partyList = procedure("crm.party.list")
.kind("read")
.scope("project")
.permission(CRM_PERMISSIONS.read)
.input(
z.object({
...inProject,
q: z.string().max(200).optional(),
after: z.string().max(64).optional(),
limit: z.number().int().min(1).max(200).optional(),
}),
)
.output(z.object({ rows: z.array(partyViewSchema), after: z.string().optional() }))
.contract()
export const partyGet = procedure("crm.party.get")
.kind("read")
.scope("project")
.permission(CRM_PERMISSIONS.read)
.input(z.object({ ...inProject, partyId }))
.output(z.object({ party: partyViewSchema, contacts: z.array(contactViewSchema) }))
.contract()
export const partyCreate = procedure("crm.party.create")
.kind("effect")
.tool({ approval: "human" })
.scope("project")
.permission(CRM_PERMISSIONS.write)
.input(
z.object({
...inProject,
kind: z.enum(["person", "organization"]),
displayName: z.string().trim().min(1).max(300),
legalName: z.string().trim().max(300).optional(),
country: z.string().regex(/^[A-Z]{2}$/),
/** A person who is the member creating it: the party is linked to them (an export or erasure of them reaches it). */
linkSelf: z.boolean().optional(),
requestId,
}),
)
.output(partyViewSchema)
.contract()
export const contactAdd = procedure("crm.contact.add")
.kind("effect")
.tool({ approval: "human" })
.scope("project")
.permission(CRM_PERMISSIONS.write)
.input(
z.object({
...inProject,
partyId,
kind: z.enum(CONTACT_KINDS),
value: z.string().trim().min(1).max(256),
purposes: z.array(z.enum(CONTACT_PURPOSES)).max(CONTACT_PURPOSES.length),
isPrimary: z.boolean(),
requestId,
}),
)
.output(contactViewSchema)
.contract()