Cannabis integrations and boundaries
Traceability, payment, storage, email, AI chat, and MCP boundaries in the current source.
The source contains no external provider adapter. Integration records describe a provider choice and queue state; they are not proof that a request reached or was accepted by a state system, payment processor, or other provider.
State traceability
- Onboarding creates one
IntegrationInstallationwithproviderType: "traceability", the provider code you supply, and statusunconfigured. Its credential reference field is not readable through GraphQL. activateIntegrationInstallationexists but is disabled (provider.installation-verification) until an adapter verifies provider capabilities directly.- Sales and other state-reported commands write an
OutboxEventwith statusqueued. No worker in the repository sends outbox events to a provider.retryStateOutboxEventonly requeuesrejected,retryable, ordead_letterevents. recordStateInboxEventwould store inbound regulator events inStateEventInboxbut is disabled (provider.authenticated-inbox) until signatures are verified by a trusted adapter.recordReconciliationRunandapproveReconciliationRunare disabled (provider.computed-reconciliation).
A queued outbox event means the sale was recorded locally. It does not mean the state traceability system received it.
Payments
There is no payment provider integration. TenderConfiguration records which tender types are accepted (cash, debit, ach, wallet, other), limited by the rule pack's allowed tender types. Cash is counted through the register shift. For non-cash tenders, finalizeCannabisSale requires the approval reference from a separate card terminal; the software does not capture or settle funds.
Storage
Keystone file storage uses S3-compatible object storage configured by S3_BUCKET_NAME, S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, and S3_ENDPOINT. Path-style addressing is chosen from the endpoint. Product images on the public menu use the publicImageUrl text field.
features/keystone/lib/mail.ts sends password-reset email when SMTP_HOST, SMTP_PORT, SMTP_USER, and SMTP_PASSWORD are set. SMTP_FROM sets the sender and SMTP_STORE_LINK sets the base URL for links. Without SMTP_HOST, reset links cannot be delivered.
AI chat and MCP
/api/completionpowers the dashboard AI chat through OpenRouter. It usesOPENROUTER_API_KEY,OPENROUTER_MODEL, and optionallyOPENROUTER_MAX_TOKENS, or keys the user supplies locally. Shared keys require a signed-in session withcanAccessDashboard.- The chat route connects to
/api/mcp-transport/[transport]for tools, but that route returns HTTP 503 for every request: the generic MCP data tool is disabled until a bounded, owner-approved integration exists. The chat therefore has no data tools.
Out of scope
- State traceability submission, polling, or webhook handling.
- Payment capture, settlement, or card-present processing.
- ID scanning hardware or third-party identity verification.
- Delivery, online ordering, and customer accounts.
- Tax filing and accounting exports.
To add a provider, write a code-owned adapter, keep credentials out of GraphQL, logs, audit metadata, and outbox payloads, authenticate inbound traffic, make retries idempotent, and only then add the matching capability to runtimeCapabilities.ts.