What it is
The support surface of the enterprise delivery product. A BYOC customer’s platform team runs our software inside their governance; when something needs us — an install refusal, an admission refusal, a health rollback, a platform change breaking capture, a question — the path is a ticket bound to delivery evidence, not a call and a pastebin. First-class support means the ticket carries the machine state needed to act on it, and its resolution is itself a delivery: most tickets close asfixed_in_entry(N) — a channel entry the customer’s cluster pulls.
Placement — what runs where
Blocking egress entirely degrades nothing (R5): ticketing is advisory-lane; an air-gapped
customer files by any out-of-band means and the evidence bundle attaches as files.
Ticket object — v1 draft
vexa-support packager shows the
operator the full payload before anything is sent.
The loop that makes it first-class
- Machine event in their cluster (preflight FAIL, Kyverno refusal, health-judge rollback,
break-glass request) → operator runs
vexa-support package <event>→ reviews → sends to the sink. Severity and kind are pre-classified by the event type. - Our side triages with the evidence already attached — the preflight report names the failing check and the §6 failure class; the refusal names the policy and the digest.
- Resolution rides the conveyor: a fix ships as a channel entry; the ticket flips to
fixed_in_entry(N); the customer’s staging pulls it, their gate promotes it, the ticket closes on their confirmation (or their cluster’s next successful sync of ≥ N, where they opt into reporting it). - Fleet-relevant causes (a platform changed under everyone) additionally publish a signed advisory on the channel — subscribers see it before they hit it.
break_glass_request is a first-class kind: the request for an incomplete-chain publication
arrives as a sev1 ticket, and the approval produces the break_glass record inside the signed
entry (ADR-0002 §5) — the audit trail is the ticket + the entry, never a side channel.
SLA surface (commitment shape)
Severity binds to delivery latency, because with a pull conveyor our release latency is the customer’s incident path (Attestation-Conveyor): sev1 = hotfix conveyor cadence (same stations, shortened soak — never a bypass), sev2 = next scheduled entry, sev3 = advisory/answer. Actual numbers are set per subscription, not here.Automated events — founder direction 2026-08-21 (same session)
The pipeline must also let the deployment call the sink itself for a set of predefined events — entirely optional, off by default, every event class individually enabled by the customer: vendor-bound bandwidth fully under their control.- Event classes (initial set):
health_degraded·sync_failed·prod_promotion(their pin moved and synced — the promotion notification) ·admission_refusal·incident_report(composed bundle) ·usage_report(metering, below). - Mechanism — no new resident software: Argo CD’s stock notifications engine (triggers + templates, configuration we ship) posts to the sink with the subscription credential; Kyverno policy reports feed refusal events. This preserves the kit’s claim verbatim: we ship configuration, not an agent.
- Contract: same shapes-not-content payloads; every class off by default; blocking all of it degrades nothing (advisory lane, R5-consistent).
Behind the sink — the vendor-side architecture (founder question 2026-08-21: “what’s behind the sink?”)
The sink itself is deliberately thin; the machinery behind it reuses what the company already runs. Nothing here is a new helpdesk product.- Two lanes behind one sink. Events (high-volume, no human) and tickets (action-needed) share ingest and schema but not workflow; promotion rules are the only bridge. This is what makes “tickets might be health callbacks built automatically” true without drowning support in telemetry.
- GitHub Issues are the workflow, not a copy of it. The bridge means a sev1 platform_change
ticket is a scope item the release train can pick up, and
fixed_in_entry(N)closure falls out of the existing close-with-release discipline rather than being built. - The store is boring: the vendor-side DB + object storage that already exist; evidence blobs stored by digest exactly like bundle members.
- Which vexa API service hosts the thin ingest remains the named open question below (admin-api is the natural candidate); everything behind it is service-agnostic.
The customer-facing lane — email confirmation or private repo? (founder question 2026-08-21)
Both patterns exist in industry; they serve different organizations. The resolution is to keep three surfaces distinct and make the human lane per-subscription configuration:- The internal workflow repo is never customer-visible. One private repo, internal-only, mirroring the ticket store — where the release train picks work up. Customers hold no access of any kind, which removes the cross-tenant-leak class by construction. (One shared repo with customer access is the one option that is simply wrong — never.)
- Default customer lane: email, bound to the ticket. On ingest the customer contact gets a
confirmation carrying the ticket id; every state change (acknowledged,
fixed_in_entry(N), closed) goes out on the same thread; replies totickets+<id>@thread back into the ticket. Why default: email is the universal ITSM adapter — ServiceNow and Jira ingest it natively, so the customer’s own ticket system stays in sync without any integration project; change boards and on-call rotations live there; zero identity or licensing friction; works for the most compliance-bound subscriber. - Offered lane for engineer-led subscriptions: a per-customer private repo
(
support-<subscription>), outside-collaborator access only, with the sync bot mirroring ticket state and conversation both ways. The reference enterprise engagement arrived through a GitHub issue — engineer-champions live there, and for them issues ARE the natural support object. Two disciplines make it safe: evidence never leaves the store (issues carry digests and pointers, not blobs — sensitive payloads stay off GitHub, which also keeps the data-residency question tractable), and access is per-repo outside collaborators, never org membership. Cost note: outside collaborators on private repos consume paid seats — a small per-customer line. - The machine API stays canonical regardless of lane: the sink ingests, the status API answers, and both human lanes are projections of the same ticket store.
tickets@vexa.ai) set up properly; and the
residency decision may exclude the GitHub lane for some subscriptions — the lane being
per-subscription configuration is exactly the accommodation for that.
Email lane — implementation sketch (and the ownership boundary)
Ownership first (founder observation 2026-08-21: “that’s largely outside the delivery product” — correct). This repo owns the contract: the ticket schema, the sink API shape, the kit’s emitter configuration, and thefixed_in_entry coupling to channel entries. The
implementation — sink service, event log, ticket store, promotion rules, email bridge, GitHub
bridge, status API — is vendor API-plane machinery and belongs with the vendor-side services
(vexa-platform’s proprietary services are the precedent home), tracked as an issue there when the
founder says go. Nothing in M3 depends on it.
Outbound (build first):
- A dedicated transactional email provider (Postmark/SES-class), never Workspace Gmail —
deliverability, suppression handling and volume are the provider’s job. Sender
tickets@vexa.ai; SPF/DKIM/DMARC on a dedicated return-path subdomain via our DNS. Provider signup + DNS changes are founder-gated ops (already flagged as the prerequisite). - Threading is the feature: first mail sets a stable
Message-ID; every state change replies withIn-Reply-To/Referencesplus a[VEXA-<id>]subject token. That is exactly what makes Gmail, Outlook, ServiceNow and Jira keep the whole ticket as one thread — the ITSM bridge is the threading discipline, not an integration. - Plain-text templates: confirmation (ticket id + what was received), state changes
(
acknowledged,fixed_in_entry(N)with the release ref,closed).
tickets+<id>@vexa.aiplus-addressing; MX/inbound-parse at the provider posting a webhook to the support service. Acceptance requires both the plus-address ticket id and a DKIM/SPF-passing sender that matches the ticket’s contacts — the id alone is a weak capability, the pair is sturdy. Attachments are stored as evidence blobs by digest with size caps; loop hygiene (Auto-Submitted, suppression, never reply to bounces).
The two-way evidence channel — founder reframe 2026-08-21
“Validation evidence channel. We send our validations, they send theirs back to us (support API).” This names what the event lanes above actually are: the upstream half of the channel.- Down: our evidence — staging validation, prod soak, provenance, signatures.
- Up (opt-in, per class, their switch): their evidence —
validation_report(their staging/gate verdicts; the kit’sapprove.shalready produces the payload: release, verdict, verdict hash, approver, entry digest), plus the existing classes (health, sync, promotion, refusals, usage).
Metering
Industry practice, surveyed:- Industry practice for BYOC/self-managed is self-reported usage under contract, with true-up/audit clauses — GitLab self-managed usage ping plus an offline usage file for air-gapped renewals; Atlassian Data Center self-declared user tiers; Red Hat self-declared subscriptions; cloud-marketplace metered billing as the procurement-friendly variant later. Structurally, in BYOC the vendor cannot measure independently — the pipe is convenience and evidence; the contract is the enforcement (pipe off ⇒ manual report per contract; the product itself is never degraded).
- The shape that fits us: per-cluster channel subscription as the floor (the access product) plus one agreed usage dimension as the scaler (e.g., active accounts / activation events), reported through this pipe on an agreed cadence.
- Two requirements before charging on it:
- A sealed definition of the metric — one definition, one carrier, queryable by the customer themselves so both sides compute the same number from the same source. (House lesson: an ambiguously-defined metric poisons every conversation it enters; the metering dimension gets a sealed schema’d definition or it does not get billed on.)
- Signed usage reports — the report is a signed statement from the customer’s side, using the same attestation machinery the delivery already carries. True-ups then compare receipts, not recollections. Nothing standard in the industry does this; for us it is a small extension and turns billing disputes into hash comparisons.
- Open (founder, Q3): the dimension itself, price levels, cadence, and whether the marketplace route (AWS/Azure/GCP metered private offers) is worth its integration cost. Nothing metering-related enters the customer docs until Q3 is decided — a documented metric is a published term.
Open questions (founder)
- Which vexa API service hosts the sink (and its auth = the subscription credential?). The sink contract will be filed as an issue on the owning repo once named — customer-visible, so founder-gated.
- Portal or API-only at v1? API-only + email bridge is the cheapest honest start.
- Retention / data residency for ticket evidence (regulated buyers will ask).
- Tier mapping — which response/delivery SLAs at which subscription tier (couples to §9 Q3).