"One server-composed reference caption (the referenced-caption rule): the caption of a record THIS record references via a declared ID-class field. A list field answers one row per entry. caption is null when the reference cannot be composed (a foreign-root record — no cross-tenant leak; a dangling id). Provider/system identifiers (Stripe refs, saga locks) never appear — they are declared external." type RefCaption { "The referencing field name on the carrying record (e.g. brandId, owners)." field: String! "The referenced id VERBATIM as the record carries it (a id; the org costCentre answers its sysId)." id: ID! "The referenced record's caption — null when not composable (foreign root · dangling)." caption: String "The DECLARED target construct type of the reference: fixed refs verbatim; a polymorphic ref answers the sibling-resolved type, null when the sibling names nothing. Schema-level knowledge — never data." refType: String "The referenced construct's id when it DIFFERS from id (a SYSID-storing field — the org costCentre), answered only when the record is readable under your root; null everywhere else (id IS the construct id). Fetch the record by refId when present, else by id." refId: ID "WHY caption is null: dangling = the referenced record does not exist (purged, or never did); unreadable = it exists but this session cannot read it (a foreign root — the word never says which). null on a captioned row." reason: String } "A resolved session principal — what an authenticated call acts as." type Principal { sessionId: ID! "The principal class — user | api | device." kind: String! "The User construct the session is a principal of — user kind only (null on api/device)." userId: ID "The acting Account — user + api kinds (the api kind's = the MINTER's Account); null on device." accountId: ID "The ApiKey the session was exchanged from — api kind only." apiKeyId: ID "The Device the session belongs to — the device kind, AND the user kind on a COMPOSITE POS session (the x-at-device-session facet); null otherwise." deviceId: ID "The device's canned hardware class — the device kind + the composite POS session's user kind; null otherwise." deviceType: String "The device's LIVE 0..1 Register binding — the device kind + the composite POS session's user kind (null while unpaired / on pi_bridge / without a device facet). The register derives its till + selling location from THIS, never from a device(id) read (a cashier tier cannot make one)." registerId: ID "The device's parent LogicalFacility (the selling location) — the device kind + the composite POS session's user kind; null otherwise." logicalFacilityId: ID "The organization the session acts in (the attribution org)." orgId: ID! "The org-group family root." rootId: ID! "The LIVE effective capability, re-derived from the account status every call — user/api kinds; null on device (a device carries trust, never authority — E)." capability: String "The session’s organization GROUP caption; read from the group record on every me — null only when the session names no group (never for a live session)." groupCaption: String "The captions of the roles the session ACTS with in its organization — user kind only; null on the api/device kinds (their authority is the key’s / the device’s, not a role’s)." roleCaptions: [String!] } "The result of a successful login — the opaque bearer token (returned ONCE) + the live principal." type LoginResult { token: String! principal: Principal! } "One admissible organization for a proven credential." type LoginChoiceOrg { orgId: ID! caption: String! "The OR-… organization sysId — the human-facing reference chip (the picker never shows a id)." sysId: String! } "One org group's picker section — the caption is a HEADER, never a choice (groups derive from the credential); only role-bearing ACTIVE orgs appear." type LoginChoiceGroup { groupId: ID! groupCaption: String! orgs: [LoginChoiceOrg!]! } "The loginChoices answer — groups caption-sorted; EMPTY means the credential PROVED but no workspace admits it (a fact, not an oracle)." type LoginChoicesResult { groups: [LoginChoiceGroup!]! } "The result of a successful consumer register/login — the opaque bearer token (returned ONCE; only its hash is ever stored) + the shopper's own profile. Consumer sessions carry NO Account and NO capability tier — the canned CONSUMER_SESSION_OPERATIONS roster is their entire authz surface (default-deny both directions)." type ConsumerAuthResult { token: String! consumer: Consumer! } "The result of a successful collaborator login — the opaque bearer token (returned ONCE; only its hash is ever stored) + the collaborator's own record. Collaborator sessions carry NO Account; their RULED-op authz is the acted-org Roles, evaluated + ENFORCED unconditionally (the api-plane law — deny-by-default)." type CollaboratorAuthResult { token: String! collaborator: Collaborator! } "The show-once invite mint." type CollaboratorInviteMint { collaborator: Collaborator! inviteToken: String! expiresAt: String! } "One org the collaborator may sign into." type CollaboratorLoginChoice { orgId: ID! caption: String! sysId: String! } "The collaboratorLoginChoices answer — orgs caption-sorted; the credential PROVED before anything answers (no oracle)." type CollaboratorLoginChoicesResult { orgs: [CollaboratorLoginChoice!]! } "The calling collaborator's access picture: the SAME projection types + the SAME pure evaluator as the staff read (no second mechanism, no drift). Evaluates DESCRIPTORS ONLY — the session/capability composition already gated this call." type CollaboratorAccess { "The session's ACTING org — the coordinate the login picked (the wire's own answer; the org-choice projection reused)." actingOrg: CollaboratorLoginChoice! "The collaborator's roles AT the acting org as loaded live (deduplicated) — non-active roles visibly contribute nothing." roles: [EffectivePermissionsRole!]! "One entry registry operation (sorted — the WHOLE descriptor universe): can THIS session do X, and WHY, for every X." operations: [EffectivePermission!]! } "The group-scoped, name-bearing construct types the caption search read-model indexes (generated from the contracts SEARCHABLE_CONSTRUCT_TYPES SoT — anti-drift)." enum SearchableType { Organization CostCentre User PhysicalFacilityLocation PhysicalFacility LogicalFacility Zone Bin Brand Season Tag Characteristic CustomUom Manufacturer Vendor Category Division OptionGroup OptionValue Style Product Collection Contact Promotion LoyaltyProgram CustomerPriceGroup Affiliate CorporateCustomer PriceList Consumer Task Team Collaborator } "One caption-search typeahead hit — the display projection of a matched construct." type SearchHit { id: ID! type: SearchableType! rootId: ID! caption: String! status: String! "The human-facing system id (sysId); null for a construct minted before the sysId scheme." sysId: String } "one cross-type search hit — the display projection + the TOKEN that matched (a caption word · the sysId · the master's code), so a face can say why the record answered." type SearchAllHit { id: ID! "The human-facing system id (sysId); null for a construct minted before the sysId scheme." sysId: String caption: String! status: String! "The folded token the prefix matched — a caption word, the sysId or the record's own code." token: String! } "the hits of ONE searchable type, in the index's order (folded token · type · id)." type SearchAllGroup { type: SearchableType! hits: [SearchAllHit!]! } "ONE typeahead page over every kind of record the caller may read — the hits grouped by type in the searchable-type order; more says rows remained beyond this page (a typeahead page is born bounded — no cursor; a face opens the full results elsewhere)." type SearchAllPage { groups: [SearchAllGroup!]! more: Boolean! } "One descriptor contribution — the carrying Role + the descriptor that matched (the verification-mechanism attribution)." type DescriptorContribution { "The Role construct id carrying the matching descriptor." roleId: ID! descriptor: RoleDescriptor! } "One operation's evaluation under the flat algorithm: permitted ⟺ at least one allow matched AND no disallow matched (default-DENY, disallow-wins; per-segment * wildcards; ONLY active roles contribute)." type EffectivePermission { "The logical service name (today: api)." service: String! "The service external operation name (a schema Query/Mutation field)." action: String! permitted: Boolean! "The allow descriptors that matched, attributed to their carrying roles." allows: [DescriptorContribution!]! "The disallow descriptors that matched (ANY entry here forces permitted: false), attributed to their carrying roles." disallows: [DescriptorContribution!]! } "An assigned role the evaluation considered — the user orgRoles selection for the org, loaded LIVE. ONLY active roles contribute: a non-active role is listed WITH its status and contributes NOTHING (neither polarity) — visibly retired from evaluation." type EffectivePermissionsRole { roleId: ID! caption: String! "The Role FSM status — non-active means retired from evaluation." status: String! } "The verification mechanism: (user, org) → the FULL effective-permission map + which role contributed each descriptor, computed by the SAME evaluator the future gate uses (preview ≡ enforcement — no second mechanism, no drift). Evaluates DESCRIPTORS ONLY: it does NOT compose the account-capability / dark-org / user-lifecycle gates." type EffectivePermissions { "The user roles AT the org as loaded live (deduplicated) — non-active roles visibly contribute nothing." roles: [EffectivePermissionsRole!]! "One entry registry operation (sorted — the WHOLE descriptor universe): can the user do X, and WHY, for every X." operations: [EffectivePermission!]! } "One structured-filter clause: `field` must be on the family's DECLARED filterable roster (taught in the listing's own doc — an unknown field's refusal re-teaches it); `op` must fit the field's kind (text contains/begins_with · enum/ref any_of · date on/before/after/between · number/money eq/lt/gt/between · flag is); `values` carries 1..25 strings — exactly ONE for the single-value operators, exactly TWO ordered low,high for `between`, one-or-more for `any_of`. Value grammars: dates are calendar days `YYYY-MM-DD` (the executor owns the UTC day window); number/money are decimal strings (compared exactly, never floated); flags are `true`/`false`; refs are ids; enum tokens must be of the declared vocabulary. Every violation refuses VALIDATION/INVALID NAMING the problem — the op stays String (not an enum) precisely so the refusal can TEACH instead of a transport parse error." input FilterClauseInput { field: String! op: String! values: [String!]! } "ABSENT means unfiltered; an EMPTY clause list refuses (say nothing, or say something)." input FilterInput { clauses: [FilterClauseInput!]! } "One sort key: missing-fact records trail in EITHER direction; ties resolve by id, so every order is total and pages are stable." input SortInput { field: String! direction: SortDirection! } "The sort directions (the contracts SORT_DIRECTIONS vocabulary VERBATIM: asc · desc)." enum SortDirection { asc desc } "One interpreted filter clause." type InterpretedClause { field: String! op: String! values: [String!]! } "One part of the written request the interpreter could not express in the filter grammar — `part` quotes the user's own words; `reason` speaks the SAME teaching voice the filter validator refuses in (an inexpressible ask and an invalid hand-built clause read identically)." type InterpretUnmappablePart { part: String! reason: String! } "One in-tenant record a reference NAME might mean (the office lookup picker pre-opens over these)." type InterpretRefCandidate { id: ID! caption: String! } "One reference name that did not resolve to EXACTLY one record — empty candidates = no match at all; the human picks (names never resolve by guess)." type InterpretAmbiguousRef { field: String! text: String! candidates: [InterpretRefCandidate!]! } "The NL interpreter's answer: grammar clauses that SURVIVED the strict validator (they pre-fill the builder — NOTHING auto-applies), the parts that could not map (worded), and the reference names needing a human pick." type InterpretedFilter { clauses: [InterpretedClause!]! unmappable: [InterpretUnmappablePart!]! ambiguousRefs: [InterpretAmbiguousRef!]! } "One plan step: `family` must be a plan-searchable family; the optional `filter` is the FilterInput grammar VERBATIM, validated against THAT family's roster exactly as its filtered listing validates it." input SearchPlanStepInput { family: String! filter: FilterInput } "The two hop directions (the contracts PLAN_HOP_DIRECTIONS vocabulary VERBATIM: outbound · inbound): outbound follows the CURRENT family's reference field to the family it names (one keyed read per distinct id); inbound walks the named family and keeps the rows whose reference field names a current match." enum SearchPlanHopDirection { outbound inbound } "One hop along a KNOWN relationship — a construct-graph reference or a roster ref field, both ends plan-searchable; a hop that is not a relationship of the current family refuses naming the legal ones — with its own optional clauses against the family it reaches." input SearchPlanHopInput { direction: SearchPlanHopDirection! field: String! family: String! filter: FilterInput } "The whole plan: the start step, zero to 3 hops in order, and the answer's ceiling (`limit` 1..200; absent = 100). Everything validates against the registry BEFORE anything runs; a JSON null on an optional field reads as absent." input SearchPlanInput { start: SearchPlanStepInput! hops: [SearchPlanHopInput!] limit: Int } "One walked family's measured size (KEYS ONLY, before any read) — `over` when the count passed the budget that remained when it was measured." type SearchPlanWalkEstimate { family: String! size: Int! over: Boolean! } "The estimate the run made BEFORE reading a record: every walked family's size plus one frontier ceiling (1000) per outbound hop." type SearchPlanEstimate { examinedMax: Int! walks: [SearchPlanWalkEstimate!]! } "One answer row — the six summary fields of a record of the plan's LAST family (open the record for more)." type SearchPlanMatch { family: String! id: ID! sysId: String caption: String! status: String! updatedAt: String } "A finished plan run: the plan in words, the pre-read estimate, the matches newest first up to the limit, the EXACT matchCount, the records examined, the elapsed ms." type SearchPlanRun { words: String! estimate: SearchPlanEstimate! matches: [SearchPlanMatch!]! matchCount: Int! examined: Int! elapsedMs: Int! } "One part of a plain-words ask no plan could express: `step` 0 = the ask as a whole (the router's own), 1 = the start family, k + 1 = hop k; `family` is null at step 0; `reason` speaks the SAME teaching voice the filter validator refuses in." type SearchPlanDraftUnmappable { step: Int! family: String part: String! reason: String! } "One reference NAME in a step's conditions that did not resolve to EXACTLY one record: the human picks from the candidates (empty = no match at all); `step` 1 = the start, k + 1 = hop k." type SearchPlanDraftAmbiguousRef { step: Int! family: String! field: String! text: String! candidates: [InterpretRefCandidate!]! } "NOTHING has run." type SearchPlanDraft { words: String! planJson: String! reasoning: String! unmappable: [SearchPlanDraftUnmappable!]! ambiguousRefs: [SearchPlanDraftAmbiguousRef!]! } "NOTHING has run and nothing is saved." type ReportDraft { words: String! specJson: String! reasoning: String! unmappable: [SearchPlanDraftUnmappable!]! ambiguousRefs: [SearchPlanDraftAmbiguousRef!]! } "ONE candidate question the assistant drafted: the strict TrainingQuestionDraft shape — the prompt, 2..6 options, the right one (0-based), the explanation, and the play step it tests (null = the whole course). NOTHING is stored: save each one you keep through createTrainingQuestion with source drafted." type TrainingQuestionDraft { prompt: String! options: [String!]! correctIndex: Int! explanation: String! stepN: Int } "The draft call's answer: the course, the kept candidates (at most the count asked) and how many the strict schema DROPPED — loud, never silent." type TrainingQuestionDrafts { courseKey: String! candidates: [TrainingQuestionDraft!]! dropped: Int! } "One training requirement that applies to YOU: the rule, its due instant (the later of your role grant and the rule's birth, plus its grace days) and whether a VALID certificate satisfies it today (certified · certificateId)." type MyTrainingRequirement { requirementId: ID! roleTemplateKey: String! courseKey: String! passMark: Int! graceDays: Int! dueAt: String! certified: Boolean! certificateId: ID "THE REFRESH STANDING — DERIVED at read time, never stored: certified AND the certificate was passed on an older version of the course (the play’s content changed, or the play is gone); false whenever not certified. Sit again to refresh." refreshDue: Boolean! "When the refresh falls due — the daily sweep’s first observation of the change + the strictest applicable graceDays; null until the sweep has observed it (the face words a due-less refresh honestly)." refreshDueAt: String } "One play's reading — the steps you have read (1-based, sorted, unique) and the last read instant." type MyTrainingPlayProgress { playKey: String! stepsRead: [Int!]! lastReadAt: String! } "One course's standing for you — sittings started TODAY (UTC), the open sitting, the last sitting, the best score, whether you ever passed, the latest certificate minted for it. 🎓: a row stands only for a course you ENGAGED with (a sitting started or sat, a practice started or handed in) — the sweep's marks alone surface none; + practiceToday · lastPracticeScore · lastPracticeAt." type MyTrainingCourse { courseKey: String! attemptsToday: Int! openAttemptId: ID lastAttemptId: ID bestScore: Int passed: Boolean! certificateId: ID "Practices started TODAY (UTC) — the practice's OWN cap (20 a day), never the sitting's." practiceToday: Int! "The last practice's score and instant — null until a practice was handed in (the last replaces the previous)." lastPracticeScore: Int lastPracticeAt: String } "YOUR training standing — the ONE self read the face needs: the requirements that apply to you · your progress per play · your courses · your open sittings · your valid certificates." type MyTraining { requirements: [MyTrainingRequirement!]! progress: [MyTrainingPlayProgress!]! courses: [MyTrainingCourse!]! openAttempts: [TrainingAttempt!]! certificates: [TrainingCertificate!]! } "ONE drawn question as the sitter sees it: the prompt, its options and the play step it tests (null = the whole course). correctIndex and explanation are NULL while the attempt is open (or doomed — never graded) and PRESENT once it is submitted — for EVERY caller: the key never rides an open sitting." type TrainingSittingQuestion { id: ID! stepN: Int prompt: String! options: [String!]! correctIndex: Int explanation: String } "ONE sitting opened whole: the attempt + its drawn questions in the STORED draw's order (a since-retired question still answers — the draw is history; a row that cannot be read is skipped). A NON-subject reader's view obeys the training.score_visibility policy of their acting organization (2 whole · 1 the answers withheld · 0 the answers and the score withheld); the subject always sees all of their own." type TrainingSitting { attempt: TrainingAttempt! questions: [TrainingSittingQuestion!]! } "ONE drawn question as you PRACTISE it (🎓: the prompt, its options and the play step (null = the whole course) — NO key: correctIndex and explanation never ride an open draw (THE NULL-KEY RULE)." type TrainingPracticeQuestion { id: ID! sysId: String! stepN: Int prompt: String! options: [String!]! } "A practice draw opened: the course, the pass mark you rehearse against (the strictest rule binding your roles for the course, else 80), the drawn questions in the order asked, when. Nothing is certified." type TrainingPracticeSitting { courseKey: String! passMark: Int! questions: [TrainingPracticeQuestion!]! startedAt: String! } "ONE question of a handed-in practice: the key, the explanation and YOUR pick (yourAnswer). A question retired for good since the start graded as missed and is not listed." type TrainingPracticeResultQuestion { id: ID! sysId: String! stepN: Int prompt: String! options: [String!]! correctIndex: Int! explanation: String! yourAnswer: Int! } "A handed-in practice: the score over the WHOLE draw, the pass mark, passed (the answer's alone — never a standing; no certificate, no notice), the readable questions with their keys and your picks, practices started today, when. The last result replaces the previous one in your own progress record." type TrainingPracticeResult { courseKey: String! score: Int! passMark: Int! passed: Boolean! questions: [TrainingPracticeResultQuestion!]! practiceToday: Int! submittedAt: String! } "What a tutor answer rests on: a step of the course (ref = the step number) or a question of the bank (ref = its sysId)." type TrainingTutorGround { kind: String! ref: String! } "The tutor's answer: plain words (at most 1200 characters), the grounds it rests on, the model that spoke. NOTHING is stored." type TrainingTutorAnswer { answer: String! grounds: [TrainingTutorGround!]! model: String! } "One background search's result set: the matches of the plan's LAST family newest first up to the plan's limit, the EXACT matchCount, the records examined, `partial` (the job halted before finishing — refused, expired, or cancelled; the partials survive), `expired` (the 7-day result set is gone; the job record stays), and the instant it expires (absent while the job still runs)." type SearchJobMatches { matches: [SearchPlanMatch!]! matchCount: Int! examined: Int! partial: Boolean! expired: Boolean! expiresAt: String } "The export file formats — DERIVED from the contracts EXPORT_FORMATS: csv (RFC 4180 through the one cell rule) · jsonl (JSON Lines — one record per line)." enum ExportFormat { csv jsonl } "One finished export's download: the presigned GET (`url`, alive until `expiresAt` — 300 s), the name to save it as, and the file's facts off the record — bytes · rowCount · format · `partial` (the run halted before the end; the file holds what was written)." type ExportJobDownload { url: String! expiresAt: String! fileName: String! bytes: Int! rowCount: Int! format: ExportFormat! partial: Boolean! } "The report measure functions — DERIVED from the contracts REPORT_MEASURE_FNS: count takes no field; sum · min · max · avg take ONE money or number field of the terminal family." enum ReportMeasureFn { count sum min max avg } "The calendar buckets a DATE group key takes — DERIVED from the contracts REPORT_DATE_BUCKETS: UTC on the stored instant; week is the ISO-8601 week (Monday-based; its year may differ from the calendar year at the boundaries)." enum ReportDateBucket { day week month quarter year } "One group key: a roster field of the terminal family of kind enum · reference · text · flag · date; `bucket` is REQUIRED on a date field and FORBIDDEN on every other kind." input ReportGroupKeyInput { field: String! bucket: ReportDateBucket } "One measure: `count` alone (no field — and it is always present whether named or not), or sum · min · max · avg over ONE money or number field (`field` required for those four)." input ReportMeasureInput { fn: ReportMeasureFn! field: String } "The report's sort — over an OUTPUT column name (`totalMinor.sum`, `createdAt.month`, `count`, a projected field, …), never a raw roster field; the direction is the contracts SORT_DIRECTIONS vocabulary. Absent: groups by count desc then the keys asc; rows newest first." input ReportSortInput { by: String! direction: SortDirection! } "The whole report spec: the plan (the SearchPlanInput grammar VERBATIM — its defaults apply, its `limit` bounds a projection's rows on the synchronous lane), then EXACTLY ONE of `columns` (1..24 — a projection) / `groupBy` (1..4 — an aggregate); `measures` (up to 8) ride ONLY with groupBy; an optional `sort`. Everything validates against the terminal family's roster BEFORE anything runs; a JSON null on an optional field reads as absent." input ReportSpecInput { plan: SearchPlanInput! columns: [String!] groupBy: [ReportGroupKeyInput!] measures: [ReportMeasureInput!] sort: ReportSortInput } "One output column of a report: its name in the row (``, `.`, `.caption`, `count`, `.`) and its kind — a roster kind (text · enum · ref · date · number · money · flag) or one the report mints: count · caption · bucket." type ReportColumn { name: String! kind: String! } "A finished synchronous report run: the report in words, the terminal family, THE OUTPUT PLAN, the rows as ONE JSON array text (`rowsJson` — the planJson carrier idiom: a row's shape is the column plan's, so the receiver parses; money renders as a decimal string by the currency's exponent, a missing group key reads `(none)`), rowCount · groupCount (0 for a projection), the records examined (the walks plus every caption hydrated), the pre-read estimate, the elapsed ms, and the reference families whose `.caption` column was OMITTED because the caller may not list them." type ReportRows { words: String! terminalFamily: String! columns: [ReportColumn!]! rowsJson: String! rowCount: Int! groupCount: Int! examined: Int! estimate: SearchPlanEstimate! elapsedMs: Int! captionsOmitted: [String!]! } "The name assist's answer: ONE cleaned-up name, already normalized under the name rule and bounded like every stored caption. It pre-fills the rename input — NOTHING auto-applies." type SuggestedCaption { suggestion: String! } "The reason assist's answer: ONE drafted change-log reason, trimmed and bounded like every stored cause reason. It pre-fills the reason input — NOTHING auto-applies." type SuggestedReason { suggestion: String! } "The record review's answer: a SHORT plain-text issue review of the record content you sent, or exactly 'No issues found.'. READ-ONLY ADVICE — it renders in a popup and changes nothing." type RecordReview { review: String! } "The note-suggest answer: ONE drafted note body. PRE-FILLS ONLY — nothing posts automatically." type SuggestedNote { suggestion: String! } "The thread-summary answer: the synopsis of the thread YOU sent — advice words, nothing changes." type ThreadSummary { summary: String! } "The form-fill assist's answer: drafted values for the empty fields you asked about, name/value pairs the office pre-fills for review, PLUS advice about what you already answered. DRAFTS ONLY — nothing applies automatically; an empty list means nothing was predictable." type FormFillSuggestion { fields: [FormFillField!]! "(the operator's verify ruling): a short check of the ANSWERED lines — formats, internal consistency, real-world plausibility (an address's parts must agree). '' = nothing to flag. Advice only — nothing is corrected automatically." advice: String! } "One drafted field value — the exact field name from your WANT lines + the text to type." type FormFillField { name: String! value: String! } "The responsive guide's answer: what this step is doing, what you have provided, what is still needed and why. GUIDANCE ONLY — rendered verbatim beside the page's static words; nothing applies or changes." type StepExplanation { explanation: String! } "The code suggest's answer: ONE derived code, free against its family's declared uniqueness scope AT ANSWER TIME (a race can still take it before you save — the save then refuses honestly). It pre-fills the code input — NOTHING auto-applies." type SuggestedCode { suggestion: String! } "The page context the assistant grounds on." input AssistantContextInput { "The current route (the location path)." route: String! "The page's title as shown." pageTitle: String! "The record family the page serves (when a catalog page)." specType: String "The looked-at record's type (detail pages)." recordType: String "The looked-at record's caption (identity, not data)." recordCaption: String "The looked-at record's sysId (identity, not data)." recordSysId: String "The URL's?filter= value VERBATIM (when filtering)." filter: String "The URL's?sort= value (when sorting)." sort: String } "One page link in an assistant answer — the path is validated against the app's OWN route directory (an invented path never reaches you)." type AssistantLink { label: String! path: String! } "The assistant's answer: grounded prose + up to five directory links. Advisory ONLY — nothing was changed on your behalf." type AssistantAnswer { answer: String! links: [AssistantLink!]! "The session Ask-context meter." contextTurns: Int! "The context ceiling — at the cap, clear the context to continue." contextTurnsMax: Int! "true once older exchanges have been condensed into the session memory (the folding marker)." contextFolded: Boolean! } "The Ask session-context meter after a clear." type AssistantContextMeter { contextTurns: Int! contextTurnsMax: Int! contextFolded: Boolean! } "An organization — THE CONTAINER: a merchant's operating organization within its org group." type Organization { id: ID! "The group-scoped human-facing system id (OR-…) — the account-number-style immutable org id." sysId: String! type: String! caption: String! "The FSM state: active | parked | suspended | doomed." status: String! "The parent org group; for an Organization parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule): owners → the Account captions (caption ONLY — never email/loginName) · primaryPhysicalFacility → the PF caption · costCentre → the CostCentre caption (by sysId)." refCaptions: [RefCaption!]! "ISO-3166 country — the org's ONE locked jurisdiction." jurisdiction: String! "Mutable human-readable organization code." code: String! "The registered legal name; the org IS the legal facility." legalName: String! "Optional trading brand name; absent = trades under the legal name." brandName: String "Optional operating-as / DBA name." operatingAsName: String "The owner Account ids; the composite create sets the creating principal's Account." owners: [ID!]! "The org's EXACTLY-ONE CostCentre sysId (CC-…) — kit-minted WITH the org; the envelope attribution anchor. Null only on a pre- org." costCentre: String "The designated PRIMARY PhysicalFacility id. Null only on a pre-composite (bootstrap-seeded) org." primaryPhysicalFacility: ID "The org's DEFAULT trading currency. Optional — but an org may not SELECT a Style until it carries one, and every selected style's non-doomed Products must price it (CONFLICT/CURRENCY_FLOOR, the three-site closure)." defaultCurrency: String "The org's Stripe Connect account ref (acct_…, 'each org = a connected account') — KIT-STAMPED by provisionStripeAccount, IMMUTABLE once set (never caller-editable). Null = unprovisioned (card payments route the platform account)." stripeAccountRef: String "Whether the connected account can take DIRECT charges (charges_enabled; the applyTender card lane routes direct only when true). Stamped at provision + refreshStripeAccountStatus. Null = unprovisioned." stripeChargesEnabled: Boolean "Whether the merchant completed Stripe-hosted onboarding (details_submitted). Stamped at provision + refresh. Null = unprovisioned." stripeDetailsSubmitted: Boolean "The owner seats' identity-verification standings. COMPLIANCE STATUS ONLY, never identity data — Stripe custodies the documents; the platform stores the outcome." ownerVerifications: [OwnerVerificationStanding!]! } "One owner seat's identity-verification standing." type OwnerVerificationStanding { "The owner Account id (the org's owners entry this standing describes)." accountId: ID! "The standing — requires_input | processing | verified | canceled (Stripe's own session vocabulary). Null: verification was never started." status: String "Present exactly when verified — the once-per-account-forever fact's instant (UTC ISO)." verifiedAt: String } "An EPHEMERAL Stripe-hosted onboarding link. The merchant completes Stripe-owned requirement collection there (the Standard shape — platform-supplied ToS refuses structurally, probed live)." type StripeOnboardingLink { url: String! "The link's Stripe-side expiry (epoch seconds)." expiresAt: Int! } "The first PhysicalFacility of the composite create — NewPhysicalFacilityInput MINUS organizationId (the parent is the org being created); references an EXISTING active PFL, tenant-scoped server-side." input FirstPhysicalFacilityInput { "Optional: default = the merchant code when given, else 'Physical Facility'." caption: String "The referenced PhysicalFacilityLocation id (the PF's address) — must exist, in-tenant, active." physicalFacilityLocationId: ID! code: String } "The first LogicalFacility of the composite create — NewLogicalFacilityInput MINUS physicalFacilityId (the parent is the first PF)." input FirstLogicalFacilityInput { "Optional: default = the merchant code when given, else 'Logical Facility'." caption: String "The operating character: store/showroom | warehouse — immutable after birth." classification: String! code: String } "The first Zone of the composite create — NewZoneInput MINUS logicalFacilityId (the parent is the first LF)." input FirstZoneInput { "Optional: default = the merchant code when given, else 'Zone'." caption: String coordinates: String code: String } "The first Bin of the composite create — NewBinInput MINUS zoneId (the parent is the first zone); coordinates REQUIRED at birth." input FirstBinInput { "Optional: default = the merchant code when given, else the coordinates locator." caption: String coordinates: String! code: String } "Create-input for the COMPOSITE org-create. The tenant (org group) AND the owners (the creating principal's Account) are derived SERVER-SIDE — never supplied. The org's CostCentre and the primary-PF designation are kit-minted." input NewOrganizationInput { "Optional: when omitted the default is the legalName; when supplied it must be non-blank." caption: String "ISO-3166 country — the org's ONE locked jurisdiction; a NEW org is gated to the launch countries: CA | US | AU | NZ — a value outside the roster refuses VALIDATION/INVALID naming the four." jurisdiction: String! "Human-readable organization code." code: String! "The registered legal name." legalName: String! brandName: String operatingAsName: String "The optional DEFAULT trading currency; required before the org can SELECT styles (the floor)." defaultCurrency: String physicalFacility: FirstPhysicalFacilityInput! logicalFacility: FirstLogicalFacilityInput! zone: FirstZoneInput! bin: FirstBinInput! } "The composite org-create result — the org + its whole min-1 chain, ALL born in ONE atomic operation. The CostCentre rides organization.costCentre as its sysId." type OrganizationCreation { organization: Organization! physicalFacility: PhysicalFacility! logicalFacility: LogicalFacility! zone: Zone! bin: Bin! } "One page of the organizations listing — the records + the opaque resume cursor." type OrganizationPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Organization!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for an Organization. jurisdiction (ONE locked country), owners (ownership transfer = its own privileged op) and costCentre (kit-minted) are NOT editable." input EditOrganizationInput { caption: String "Mutable human-readable organization code." code: String "The registered legal name." legalName: String brandName: String operatingAsName: String "RE-DESIGNATE the primary PhysicalFacility. The new PF must be in-tenant, BELONG to this org, and be active; the OLD designation releases implicitly (the guard reads the pointer live)." primaryPhysicalFacility: ID "The DEFAULT trading currency. A CHANGE under live OrgStyle selections is floor-gated: every selected style's non-doomed Products must already carry the NEW currency (CONFLICT/CURRENCY_FLOOR naming the {styleId, productId} gaps — site 3)." defaultCurrency: String } "One system-shipped IMMUTABLE Characteristic template; identical for every tenant." type CannedCharacteristic { "The stable registry key a copyCannedCharacteristic names (kebab-case)." key: String! caption: String! valueType: CharacteristicValueType! grammar: CharacteristicGrammar "The canned-UoM unit code (number-typed templates only)." unit: String } "Copy-input for copyCannedCharacteristic: the template key + optional caption/code overrides; the template payload (valueType/grammar/unit) copies VERBATIM — customize AFTER the copy via updateCharacteristic." input CopyCannedCharacteristicInput { "The canned template key (cannedCharacteristics lists them) — an unknown key is refused VALIDATION/INVALID." key: String! "Optional caption override; default = the template caption." caption: String "Optional code override; default = the template key." code: String } "One canned unit of measure." type CannedUom { code: String! caption: String! dimensionClass: UomDimensionClass! "The conversion factor to the class BASE unit (count=each · mass=kg · volume=l · length=m · area=m2 · time=day); base units carry exactly 1." factorToBase: Float! } "The nested Product block of createItem — the whole-style pricing carrier." input ItemProductInput { "Optional: default = the merchant code when given, else 'Product'." caption: String code: String "The RRP map — REQUIRED, at least 1 entry." rrp: [MoneyEntryInput!]! msrp: [MoneyEntryInput!] tagIds: [ID!] } "The nested Variant block of createItem — the single zero-dimension cell (the coordinate is FORCED empty; the stock-UoM pair defaults (canned, each) and is immutable)." input ItemVariantInput { "Optional: default = the merchant code when given, else 'Variant'." caption: String code: String stockUomKind: StockUomKind stockUomRef: String } "Create-input for createItem. The style-level fields sit at the top (the item IS its style to a general-merch merchant); styleType is FORCED simple and the scheme FORCED zero-dimension — NOT inputs. The tenant is derived SERVER-SIDE." input NewItemInput { "Optional style caption: default = the merchant code when given, else 'Style'." caption: String code: String brandId: ID seasonIds: [ID!] categoryPlacements: [StylePlacementEntryInput!] tagIds: [ID!] characteristicEntries: [StyleCharacteristicEntryInput!] product: ItemProductInput! variant: ItemVariantInput! } "The composite item-create result — the zero-dimension simple Style + the whole-style Product + the single Variant, ALL born in ONE atomic transaction." type ItemCreation { style: Style! product: Product! variant: Variant! } "ONE ledgered identifier assignment: a kind + value borne by a Variant over an assignment window. sysId-LESS; IMMUTABLE (no edit op exists; supersededAt is the ONE set-once SYSTEM stamp; doomed = VOIDED, a correction)." type IdentifierEntry { id: ID! type: String! "The derived display caption — kind + value; never editable." caption: String! "The FSM state: active | doomed (doomed = VOIDED — excluded from listings/resolution)." status: String! "The bearer Variant." parentId: ID! rootId: ID! "The canned identifier kind (sku | plu | gtin:upc-a | gtin:ean-13 | gtin:itf-14 — SPEC_REGISTRY, server-validated)." kind: String! "The identifier value VERBATIM as authored (merchant-/-authored)." value: String! "The org whose namespace the assignment occupies — present for org-scoped kinds (plu/gtin), absent for the group-scoped sku." organizationId: ID "The assignment instant." assignedAt: String! "The supersession instant." supersededAt: String createdAt: String! updatedAt: String! revision: ID! revisionNum: Int! } "One resolution hit (the locked -trail rule): the ledgered entry + its hydrated bearer Variant + the current/outdated flag." type IdentifierResolutionMatch { entry: IdentifierEntry! variant: Variant! "true when the assignment window is still OPEN (supersededAt absent) — an old printed label resolves with current: false (outdated),." current: Boolean! } "Assign-input for assignIdentifier. organizationId is REQUIRED for org-scoped kinds (plu/gtin) and REFUSED for sku; override is GTIN-only." input AssignIdentifierInput { "The bearer Variant id — tenant-scoped + ACTIVE-gated server-side." variantId: ID! "The canned kind (sku | plu | gtin:upc-a | gtin:ean-13 | gtin:itf-14) — server-validated BEFORE the generic parse." kind: String! "The value, verbatim — per-kind shape-validated (sku non-whitespace 1..64 · plu 1..8 digits [— the contracts PLU_VALUE_PATTERN window] · gtin check-digit)." value: String! organizationId: ID override: Boolean } "Retire-input for retireIdentifier." input RetireIdentifierInput { variantId: ID! kind: String! organizationId: ID } "One evaluated collection hit: the surviving Product + whether an ACTIVE CollectionMember record backs it (a pin on dynamic collections; every static hit is member-backed)." type CollectionProductHit { product: Product! "true when an ACTIVE CollectionMember record backs this hit — the explicit-curation flag." pinned: Boolean! } "One option selection on a listed variant." type AgentCatalogSelectedOption { optionGroupId: ID! "The axis caption (Color · Size …)." name: String! optionValueId: ID! "The value caption (Blue · Large …)." label: String! } "One selectable value of a product option; `available`/`exists` are filled by agentChannelCatalogProduct ONLY (relative to the effective selections)." type AgentCatalogOptionValue { id: ID! label: String! "A listed variant with this value AND the other effective selections is available — detail read only." available: Boolean "A listed variant with this value AND the other effective selections exists — detail read only." exists: Boolean } "One option axis across a product's LISTED variants (values in OptionValue ordinal order)." type AgentCatalogOption { optionGroupId: ID! name: String! values: [AgentCatalogOptionValue!]! } "A GTIN identifier as a released barcode standard: UPC | EAN | GTIN." type AgentCatalogBarcode { type: String! value: String! } "Lookup correlation — which request identifier reached this variant and how: exact | featured (agentChannelCatalogLookup ONLY)." type AgentCatalogInput { id: String! match: String! } "A category the product's Style is placed in — the id + the merchant caption (the search filter matches the caption)." type AgentCatalogCategory { id: ID! value: String! } "One LISTED variant: active, not vetoed, ranged at the channel's selling location with a sale-price window in effect NOW, priced by the channel's PriceList plane when it yields (else the standing window), in the organization's currency." type AgentCatalogVariant { "The Variant id — the released item.id a checkout line names." id: ID! productId: ID! "The variant caption." title: String! code: String "The current sku identifier, when assigned." sku: String barcodes: [AgentCatalogBarcode!]! "The organization's currency — every price on the listing is in it." currency: String! "The effective unit price in minor units." priceMinor: Int! "The standing window price in minor units — present ONLY when the PriceList plane priced LOWER (the honest strikethrough)." listPriceMinor: Int "The SalePrice window in effect (the lapse law's witness)." salePriceId: ID! "The InventoryItem at the selling location (the ranging witness)." inventoryItemId: ID! "A stockless style type (service · bundle): always available, no status, never a figure." stockless: Boolean! available: Boolean! "in_stock | out_of_stock — absent for a stockless variant." availabilityStatus: String "The available quantity (on hand − reserved) as the engine's decimal string — ONLY when the channel shows stock levels and the variant is stocked." availableQuantity: String options: [AgentCatalogSelectedOption!]! "Lookup correlation — agentChannelCatalogLookup ONLY; null elsewhere." inputs: [AgentCatalogInput!] } "One LISTED product: in the union of the channel's ACTIVE listed Collections (the evaluator), with at least one listed variant; the words from the decorations (display-name · description · short-description), else the captions." type AgentCatalogProduct { id: ID! styleId: ID! title: String! description: String shortDescription: String code: String "The Style's Brand caption, when present." brand: String categories: [AgentCatalogCategory!]! "Tag captions (the product's ∪ the style's)." tags: [String!]! currency: String! priceMinMinor: Int! priceMaxMinor: Int! listPriceMinMinor: Int listPriceMaxMinor: Int "The option axes across the LISTED variants (the Style scheme order)." options: [AgentCatalogOption!]! "The listed variants — at least one." variants: [AgentCatalogVariant!]! "The listed collections that carry this product (collection order)." collectionIds: [ID!]! "True when an ACTIVE CollectionMember pins it in any listed collection." pinned: Boolean! } "One page of agentChannelCatalogSearch — the listing order (collection order · the evaluator's order within a collection); nextCursor present iff a page follows; truncated when the listing was cut at its ceiling." type AgentChannelCatalogPage { products: [AgentCatalogProduct!]! nextCursor: String totalCount: Int! truncated: Boolean! } "The agentChannelCatalogLookup answer — every returned variant carries inputs (which identifiers reached it); notFound names the identifiers that resolved to nothing listed (request order)." type AgentChannelCatalogLookup { products: [AgentCatalogProduct!]! notFound: [String!]! truncated: Boolean! } "The agentChannelCatalogProduct answer — null product when the identifier resolves to nothing listed; selected = the effective selections after relaxation; options carry available/exists relative to them." type AgentChannelCatalogDetail { product: AgentCatalogProduct selected: [AgentCatalogSelectedOption!]! options: [AgentCatalogOption!]! truncated: Boolean! } "A requested option selection for agentChannelCatalogProduct — by option-value id when known (preferred), else by axis name + value label." input AgentCatalogSelectedOptionInput { name: String! label: String! id: ID } "The fulfillment method TYPES a checkout may choose (the Order option methods ship · pickup_instore · pickup_curbside map onto them) (the released well-known values this business serves): shipping | pickup." enum AgentCheckoutFulfillmentType { shipping pickup } "One checkout line to sell — the listed Variant + whole units." input AgentCheckoutLineInput { variantId: ID! quantity: Int! } "The platform-captured consent decisions (the four UCP purposes: marketing · analytics · preferences · sale_or_sharing) — a field present = asserted; absent = the channel default speaks." input AgentCheckoutConsentInput { marketing: Boolean analytics: Boolean preferences: Boolean sale_or_sharing: Boolean } "The buyer as the platform gave them — names · email · phone (the channel's requireBuyerEmail/requireBuyerPhone decide what is MISSING; an invalid email is a recoverable message, never a refusal) · consent." input AgentCheckoutBuyerInput { firstName: String lastName: String email: String phone: String consent: AgentCheckoutConsentInput } "The platform's shipping address AS RECEIVED — every field optional; the engine judges completeness (name · ≥ 1 address line · city · an ISO alpha-2 country) and messages the gaps; id = the platform's own destination id (echoed)." input AgentCheckoutShipToInput { id: String name: String addressLines: [String!] city: String region: String postalCode: String countryCode: String phone: String } "The delivery choice — ONE method per checkout: shipping (the address + a rate-card optionId) or pickup (one of the channel's pickup locations + pickup_instore | pickup_curbside)." input AgentCheckoutFulfillmentInput { type: AgentCheckoutFulfillmentType! shipTo: AgentCheckoutShipToInput pickupLogicalFacilityId: ID optionId: String } "The whole checkout as the platform states it (create = the birth; update = FULL REPLACEMENT — the released law)." input AgentCheckoutInput { lines: [AgentCheckoutLineInput!]! buyer: AgentCheckoutBuyerInput fulfillment: AgentCheckoutFulfillmentInput "The discount extension: the platform's codes — replacement semantics (the list replaces the held coupon; clears); absent = untouched. At most 8 codes, each at most 64 characters; matched case-insensitively. A rejected code is a warning message at $.discounts.codes[i], never a refusal." discountCodes: [String!] } "One message the status rule raised — a released code (out_of_stock · item_unavailable · address_undeliverable · eligibility_invalid · missing · discount_code_invalid · …), the kind (error | warning), an RFC 9535 path into the released response, the words, the severity (recoverable | unrecoverable — an error's member; a warning carries none on the released wire)." type AgentCheckoutMessage { code: String! "error | warning (a rejected discount code is a warning)." kind: String! path: String content: String! severity: String! } "One quoted line — the Order line (lineNo) · the listed variant · whole units · the plane-aware unit price · base − discounts + tax = total (minor units) · listed/available at quote time." type AgentCheckoutLine { lineNo: Int! variantId: ID! productId: ID! title: String! quantity: Int! unitPriceMinor: Int! baseMinor: Int! discountMinor: Int! taxMinor: Int! totalMinor: Int! listed: Boolean! available: Boolean! } "One fulfillment option on offer — a rate card (fee · earliest/latest instants from handling + transit days) or a pickup choice (fee 0)." type AgentCheckoutOption { id: String! title: String! description: String feeMinor: Int! earliestAt: String latestAt: String } "A postal address (the facility records' own shape) — a pickup location's." type AgentCheckoutPostalAddress { line1: String! line2: String city: String! region: String postalCode: String countryCode: String! } "One of the channel's pickup locations (an ACTIVE LogicalFacility) — the name + its facility address when resolvable." type AgentCheckoutPickupLocation { logicalFacilityId: ID! name: String! address: AgentCheckoutPostalAddress } "One consent purpose's standing — the platform's captured decision (source platform) or the channel's default (source business)." type AgentCheckoutConsent { purpose: String! granted: Boolean! source: String! } "The fulfillment offer + the selection — the offered types · the selected type · the stored destination (+ the platform's id) · the pickup locations · the options for the selected type + destination · the selected option · its fee." type AgentCheckoutFulfillment { offered: [AgentCheckoutFulfillmentType!]! selectedType: AgentCheckoutFulfillmentType shipTo: OrderShipTo shipToId: String pickupLocations: [AgentCheckoutPickupLocation!]! selectedPickupLogicalFacilityId: ID options: [AgentCheckoutOption!]! selectedOptionId: String feeMinor: Int! } "The quote's money (minor units): subtotal − discounts + tax + the fulfillment fee = total." type AgentCheckoutTotals { subtotalMinor: Int! discountMinor: Int! taxMinor: Int! fulfillmentMinor: Int! totalMinor: Int! } "The discount extension's view: the platform's codes as submitted on a create/update (rejected codes included — the spec echoes them) or as held on a read + every applied discount (code-based and automatic). Always built; the shop's host renders it only when the channel advertises the extension (allowDiscountCodes)." type AgentCheckoutDiscounts { codes: [String!]! applied: [AgentCheckoutAppliedDiscount!]! } "One applied discount: the coupon code (absent on an automatic discount) · the caption · the applied reduction in minor units (> 0 — the pipeline's own per-entry figure, never re-derived) · automatic (a promotion · loyalty · employee · manual entry) · the allocation method (each = a line-level entry applied per item | across = an order-level entry split pro-rata) · the pipeline's priority (1 = applied first) · the per-line allocations when the pipeline can name them (Σ == amountMinor; absent otherwise)." type AgentCheckoutAppliedDiscount { code: String title: String! amountMinor: Int! automatic: Boolean! method: String! priority: Int! allocations: [AgentCheckoutDiscountAllocation!] } "One line's share of an applied discount: the Order line number + the share in minor units." type AgentCheckoutDiscountAllocation { lineNo: Int! amountMinor: Int! } "The buyer as stored — names · email · phone." type AgentCheckoutBuyer { firstName: String lastName: String email: String phone: String } "THE AGENT CHECKOUT VIEW: the draft Order as a UCP checkout session at NOW — status ∈ incomplete | requires_escalation | ready_for_complete | complete_in_progress | completed | canceled (the status rule) over its lines, buyer, consent, fulfillment offer, totals, discounts and messages." type AgentCheckout { orderId: ID! revision: ID! revisionNum: Int! agentChannelId: ID! organizationId: ID! "The platform that opened it — absent on a staff test drive." platformProfileUrl: String "THE LINKED BUYER: the Consumer this checkout is stamped with — the platform's user token named them (or a staff test drive did); absent on a guest checkout." consumerId: ID currency: String! "The draft Order's own status (draft · sent · accepted · expired · cancelled)." orderStatus: String! status: String! "The session's expiry (the draft's validUntil = birth + the channel's checkout TTL)." validUntil: String lines: [AgentCheckoutLine!]! buyer: AgentCheckoutBuyer consent: [AgentCheckoutConsent!]! fulfillment: AgentCheckoutFulfillment! totals: AgentCheckoutTotals! "The discount extension's view: the codes + the applied discounts; always present on the wire." discounts: AgentCheckoutDiscounts! messages: [AgentCheckoutMessage!]! "The minted sale — present iff status is completed." order: AgentCheckoutOrderRef "The instrument that paid — display-safe (never a credential); present iff the checkout completed." payment: AgentCheckoutPayment } "The minted sale a completed checkout names: its id + human label (the sale's sysId); the door adds the permalink from the business host." type AgentCheckoutOrderRef { id: ID! sysId: String! "THE RECEIPT TOKEN: the sale’s stored capability; the door builds order.permalink_url from it (absent on a pre- sale)." receiptToken: String } "The display-safe echo of the instrument that paid: the platform's ids + the processor's brand/last four." type AgentCheckoutPayment { instrumentId: String! handlerId: String! type: String! brand: String last4: String } "The credential the platform submits at complete: a token_credential — the type (PAYMENT_GATEWAY for Google Pay via Stripe) + the token (a Stripe tok_/pm_ id or the Stripe Token object as a JSON string); a raw card number is refused." input AgentCheckoutCredentialInput { type: String! token: String! } "Display words for the instrument — brand · last digits · expiry; optional, presentational only." input AgentCheckoutInstrumentDisplayInput { brand: String lastDigits: String expiryMonth: Int expiryYear: Int } "The selected payment instrument: the platform's instrument id · the handler id the business advertises (gpay) · the instrument type (card) · the credential · display words." input AgentCheckoutInstrumentInput { id: String! handlerId: String! type: String! credential: AgentCheckoutCredentialInput! display: AgentCheckoutInstrumentDisplayInput } "THE COMPLETE request: the ONE selected instrument." input AgentCheckoutCompleteInput { instrument: AgentCheckoutInstrumentInput! } "One sold line as the platform reads it: the frozen money + the three quantity counts (whole units) + the derived status ∈ processing | partial | fulfilled | removed." type AgentOrderLine { lineNo: Int! variantId: ID! productId: ID! title: String! unitPriceMinor: Int! quantityOriginal: Int! quantityTotal: Int! quantityFulfilled: Int! baseMinor: Int! discountMinor: Int! taxMinor: Int! totalMinor: Int! status: String! } "One line share of a fulfillment event." type AgentOrderEventLine { lineNo: Int! quantity: Int! } "One fulfillment event — a Fulfillment record's state as an append-only shipment fact: type ∈ processing | shipped | ready_for_pickup | delivered | canceled; tracking when shipped." type AgentOrderEvent { id: ID! occurredAt: String! type: String! lines: [AgentOrderEventLine!]! trackingRef: String carrierName: String description: String } "One post-order adjustment: type ∈ refund | cancellation — a Refund (signed minor units, negative = money returned) or the sale's own cancellation; status pending | completed | failed." type AgentOrderAdjustment { id: ID! type: String! occurredAt: String! status: String! amountMinor: Int description: String } "The fulfillment side: the option the buyer chose (ONE expectation) · its destination (the ship-to or the pickup location) · the buyer-facing words · the events so far." type AgentOrderFulfillment { methodType: String! option: OrderFulfillmentOption! shipTo: OrderShipTo pickupLocation: AgentCheckoutPickupLocation description: String events: [AgentOrderEvent!]! } "THE AGENT ORDER VIEW: the minted sale as the platform reads it — the released dev.ucp.shopping.order rendered by the door from these words; permalinkUrl = the order resource's own URL on the business host." type AgentOrder { orderId: ID! sysId: String! "The checkout this sale was minted from." checkoutId: ID! agentChannelId: ID! organizationId: ID! "The platform that originated it — absent on a staff test drive." platformProfileUrl: String "THE LINKED BUYER: the Consumer the sale is stamped with; a linked platform reads the buyer's orders through it; absent on a guest sale." consumerId: ID currency: String! "The sale's own status (placed · completed · cancelled · …)." orderStatus: String! paymentState: String! fulfillmentState: String! placedAt: String! permalinkUrl: String! "THE RECEIPT TOKEN: the sale’s stored capability the door’s permalink is built from; absent on a pre- sale." receiptToken: String lines: [AgentOrderLine!]! buyer: AgentCheckoutBuyer fulfillment: AgentOrderFulfillment! adjustments: [AgentOrderAdjustment!]! totals: AgentCheckoutTotals! } "The 5 stock buckets. available is NOT a bucket: it is ALWAYS derived (on_hand − reserved) and never stored." enum StockBucket { on_hand reserved in_transit damaged held } "The 15 canned movement types." enum StockMovementType { receive transfer_out transfer_in adjust count_correct sell return build_consume build_produce break_consume break_produce assemble_on_fly relocate reclass rtv cost_true_up reserve release } "A SIGNED money delta — the movement's value impact: receive +qty x cost · adjust ±qty x WMA · reclass none. The amount is a SIGNED strict decimal string (the MoneyEntry grammar with a sign)." type CostImpact { currency: String! amount: String! } "ONE posted Stock-Card movement fact: the magnitude rides quantity (POSITIVE), the direction rides fromBucket/toBucket (the classic in/out card form; a bucket balance = sum of to minus sum of from). sysId-LESS (the class); IMMUTABLE — NO update or doom op exists; posted ONLY by the movement mutations in ONE transaction with the II cache stamp." type InventoryEntry { id: ID! type: String! "The derived display caption — movement + quantity; never editable." caption: String! "The FSM state: active | doomed (doomed = VOIDED, reserved for a future void-family flow — excluded from the card and the verify sum)." status: String! "The parent InventoryItem." parentId: ID! rootId: ID! "The canned movement type (SPEC_REGISTRY — the ops produce receive | adjust | reclass)." movement: StockMovementType! "The movement MAGNITUDE — a POSITIVE strict decimal string in the variant stock UoM; direction rides the buckets." quantity: String! "The bucket this movement DRAINS (adjust-down · reclass source); absent for receive / adjust-up." fromBucket: StockBucket "The bucket this movement FILLS (receive · adjust-up · reclass target); absent for adjust-down." toBucket: StockBucket "The receive unit cost. Receive-only." unitCost: MoneyEntry "The SIGNED value delta this movement caused; absent when no cost basis exists." costImpact: CostImpact "The reason code/text — REQUIRED on adjust; carries the canned held reason on a reclass into held." reason: String "Provenance document refs (bounded free strings — the PO/receipt refs land typed)." refs: [String!] "Present (true) EXACTLY when this movement drove a touched bucket negative." overcommitted: Boolean "The bin this movement LEFT." fromBinId: ID "The bin this movement ENTERED." toBinId: ID "The lot identity the relocate moved." lotCode: String createdAt: String! updatedAt: String! revision: ID! revisionNum: Int! } "One StockRecord bin/lot SHARD of an InventoryItem: NOT a construct — sysId-less and FSM-less, existing only where stock has landed in a bin (zero records = everything un-binned, the small-merchant case). Carries ONLY the three LOCATABLE buckets (reserved is a claim overlay, in_transit is not physically here — both stay on the item caches); quantities are NON-NEGATIVE (a relocate refuses driving a record negative — CONFLICT/INSUFFICIENT_STOCK). The DERIVED un-binned pool = item caches minus the record sums (see verifyInventoryItem). Records persist at zero; a zeroed record does NOT block its bin (the moved-or-zeroed rule)." type StockRecord { "The owning InventoryItem." inventoryItemId: ID! "The Bin holding this shard." binId: ID! "The lot identity." lotCode: String "The lot expiry (UTC instant) — birth-stamped; a later mismatch refuses; a record missing it is enriched by the next lotted relocate that supplies one." lotExpiresAt: String onHandQty: String! damagedQty: String! heldQty: String! createdAt: String! updatedAt: String! revisionNum: Int! } "A movement outcome: the POSTED entry + the post-movement InventoryItem — written in ONE transaction, so they can never disagree." type StockMovement { inventoryItem: InventoryItem! entry: InventoryEntry! } "The five cached bucket balances by field (the verify read projection; available is derived, not a bucket)." type StockBucketTotals { onHandQty: String! reservedQty: String! inTransitQty: String! damagedQty: String! heldQty: String! } "The two-way reconciliation report: the Stock-Card sum per bucket (ACTIVE entries; to minus from) vs the cached balances on the II." type InventoryVerification { inventoryItem: InventoryItem! "ACTIVE (non-voided) entries summed." entryCount: Int! computed: StockBucketTotals! cached: StockBucketTotals! "true when every computed FLOW bucket equals its cached balance AND the record shards reconcile (recordsConsistent) AND the reserved claim overlay reconciles vs the open transfer docs (reservedConsistent) — exact decimal comparison throughout." consistent: Boolean! "The item StockRecord shard rows." recordCount: Int! "Sum of the record shards per bucket." binned: StockBucketTotals! "The DERIVED un-binned pool per bucket = cached minus binned." unbinned: StockBucketTotals! "true when the per-(bin, lot, bucket) recompute from the relocate entries equals every stored record, every record is non-negative, and no non-zero recomputed cell lacks its row." recordsConsistent: Boolean! "Sum reserved by OPEN transfer docs naming this item as a source line." openTransferReservedQty: String! "true when the cached reserved equals the open-doc sum." reservedConsistent: Boolean! } "Receive-input for receiveStock. unitCost is REQUIRED with an EXPLICIT currency: the FIRST costed receive fixes the II cost currency; a later mismatch is refused naming the expected currency." input ReceiveStockInput { "The target InventoryItem id — tenant-scoped + ACTIVE-gated + STOCKED-gated server-side." inventoryItemId: ID! "The received quantity — a strictly POSITIVE decimal string (the variant stock UoM, IV-g)." quantity: String! "The unit cost {currency, amount} — the WMA input." unitCost: MoneyEntryInput! "Optional caption override for the posted entry." caption: String refs: [String!] } "Adjust-input for adjustStock. A negative adjust may drive the bucket negative — allowed + evented. Value at CURRENT WMA." input AdjustStockInput { inventoryItemId: ID! "The SIGNED delta (non-zero decimal string) — positive writes on, negative writes off." quantity: String! "The adjusted bucket — on_hand | damaged | held; DEFAULTED to on_hand when omitted." bucket: StockBucket "REQUIRED: the merchant adjustment reason." reason: String! caption: String refs: [String!] } "Reclass-input for reclassStock. heldReason is REQUIRED exactly when the target is held and REFUSED otherwise." input ReclassStockInput { inventoryItemId: ID! "The moved quantity — a strictly POSITIVE decimal string." quantity: String! fromBucket: StockBucket! toBucket: StockBucket! "The canned held reason — required iff toBucket is held." heldReason: String caption: String refs: [String!] } "An assembly movement outcome: the KIT leg + the component legs of the ONE transaction, in recipe order (BOM-edge id ASC). The entry movement types (build_consume | build_produce | break_consume | break_produce) carry direction." type StockAssembly { kit: StockMovement! components: [StockMovement!]! } "Build-input for buildStock: quantity = the kits PRODUCED; every live component edge consumes edgeQty x quantity from on_hand at the SAME facility (on_hand to on_hand only). caption rides the KIT leg; refs ride EVERY leg." input BuildStockInput { "The KIT InventoryItem id — tenant-scoped + ACTIVE + STOCKED + kit-TYPED server-side (bundles NEVER build)." inventoryItemId: ID! "The kits produced — a strictly POSITIVE decimal string." quantity: String! "Optional caption override for the KIT (build_produce) entry." caption: String refs: [String!] } "Break-input for breakStock." input BreakStockInput { "The KIT InventoryItem id — tenant-scoped + ACTIVE + STOCKED + kit-TYPED server-side." inventoryItemId: ID! "The kits broken — a strictly POSITIVE decimal string." quantity: String! "Optional caption override for the KIT (break_consume) entry." caption: String refs: [String!] } "Relocate-input for relocateStock. A location is a Bin or (side absent) the DERIVED un-binned pool: bin-to-bin, pool-to-bin (put-away), bin-to-pool (take-out); at least ONE side names a bin and an equal pair refuses. Both bins must belong to the item logical facility (relocate is intra-LF by law); the to-bin must be ACTIVE (the from-bin may be any status — the healing direction). Lot fields ride ONLY on lot-controlled items." input RelocateStockInput { "The InventoryItem id — tenant-scoped + ACTIVE-gated + STOCKED-gated server-side." inventoryItemId: ID! "The moved quantity — a strictly POSITIVE decimal string." quantity: String! "The relocated bucket — on_hand | damaged | held; DEFAULTED to on_hand when omitted." bucket: StockBucket "The source Bin id; ABSENT = the un-binned pool." fromBinId: ID "The target Bin id; ABSENT = the un-binned pool." toBinId: ID "The lot identity." lotCode: String "The lot expiry (UTC instant) — birth-stamps the lot record; a later mismatch refuses; a record missing it is enriched." lotExpiresAt: String caption: String refs: [String!] } "One caller-supplied line at create." input TransferLineInput { "The SOURCE InventoryItem id — tenant-scoped + ACTIVE + STOCKED server-side." inventoryItemId: ID! "The quantity to move — a strictly POSITIVE decimal string." quantity: String! } "Create-input for createTransfer. The tenant is derived SERVER-SIDE from the principal; both LFs are tenant-scoped + ACTIVE-gated; the weight (light | shipped) + the org attribution derive from the live facility spine; a same-LF pair refuses (an intra-LF move is relocateStock); lines are FIXED at create (1..24 — the NAMED ceiling, distinct source IIs)." input CreateTransferInput { "Optional caption." caption: String "The SOURCE LogicalFacility id (the containment parent)." sourceLogicalFacilityId: ID! "The DESTINATION LogicalFacility id (pointer ref; must differ from the source)." destinationLogicalFacilityId: ID! "The lines (1..24)." lines: [TransferLineInput!]! } "Ship-input for shipTransfer (ready -> in_transit). The optional shipped metadata lands HERE (known at ship time, not before)." input ShipTransferInput { "The Transfer id — tenant-scoped server-side." transferId: ID! "Optional expected-arrival instant (UTC ISO-8601 — drives the future in-transit aging strand)." expectedArrivalAt: String "Optional carrier / tracking references (bounded free strings, max 8 x 128)." carrierRefs: [String!] } "One receipt landing: a line (by lineNo) x a landing bucket — on_hand (the default) or held (reason-coded, strict both ways). One receipt per (line, landing bucket) per call; a line may split across both." input TransferReceiptInput { "The line being received (1-based, as stored)." lineNo: Int! "The quantity landing NOW — strictly positive; cumulative receipts never exceed the line shipped quantity (over-receipt refuses CONFLICT/DISCREPANCY)." quantity: String! "The landing bucket — on_hand | held ONLY (DEFAULTED to on_hand when omitted; a foreign bucket refuses)." toBucket: StockBucket "The canned held reason — required iff toBucket is held." heldReason: String } "One DECLARED-surplus landing." input TransferSurplusInput { "The line whose surplus arrived (1-based, as stored)." lineNo: Int! "The surplus quantity landing NOW — strictly positive; NEVER counts toward receivedQty (stamps unplannedQty)." quantity: String! "The landing bucket — on_hand | held ONLY (DEFAULTED to on_hand when omitted; the receipts matrix verbatim)." toBucket: StockBucket "The canned held reason — required iff toBucket is held." heldReason: String } "One WRONG-ITEM arrival: a destination-LF junction x quantity, booked QTY-ONLY (no transfer line = no frozen cost; the source's correction carries the true cost)." input TransferUnplannedArrivalInput { "The receiving junction (variant x the transfer DESTINATION LF — the custody law; scoped + ACTIVE)." inventoryItemId: ID! "The quantity that physically arrived — strictly positive." quantity: String! "The landing bucket — on_hand | held ONLY (DEFAULTED to on_hand when omitted)." toBucket: StockBucket "The canned held reason — required iff toBucket is held." heldReason: String "Optional free-text reason riding the movement entry." reason: String } "Receive-input for receiveTransfer (partial + repeatable; + the / declared accepted-unplanned lanes)." input ReceiveTransferInput { "The Transfer id — tenant-scoped server-side." transferId: ID! "The documented landings (at most one per line x landing bucket — max 48; may be EMPTY when a declared lane is supplied — a receipts-empty call posts movements WITHOUT touching the doc status)." receipts: [TransferReceiptInput!]! "DECLARED surplus per line." surplus: [TransferSurplusInput!] "Wrong-item arrivals." unplannedArrivals: [TransferUnplannedArrivalInput!] } "One residual disposition: a line (by lineNo) x a disposition code x a quantity. The resolve codes are loss | damaged | found | scrap | returned; a line residual may split across codes." input TransferResolutionInput { "The line whose residual is being disposed." lineNo: Int! "The residual quantity disposed under this code — strictly positive; at most the line residual." quantity: String! "The disposition code — loss | damaged | found | scrap | returned (server-validated; the registry is vocabulary-complete x6)." disposition: String! "Optional free-text reason riding the disposition movement entry." reason: String } "Resolve-input for resolveTransfer." input ResolveTransferInput { "The Transfer id — tenant-scoped server-side." transferId: ID! "The dispositions (min 1; at most one per line x disposition code — max 120; the PORT action budget is the binding bound)." resolutions: [TransferResolutionInput!]! } "One caller-supplied line at create." input TransferRequestLineInput { "The requested variant id — tenant-scoped server-side; its requesting-LF InventoryItem junction must EXIST." variantId: ID! "The requested quantity — a strictly POSITIVE decimal string." quantity: String! "No further notes." orderLineRef: SpecialOrderLineRefInput } "Create-input for createTransferRequest. The tenant is derived SERVER-SIDE from the principal; the requesting LF is tenant-scoped + ACTIVE-gated (+ the target LF resolvable when named — a target == requesting refuses); the org attribution derives from the live facility spine; the demand metadata (neededBy / priority) is BIRTH-FIXED (TR-k); lines are FIXED at create (1..24 — the NAMED ceiling, TR-o; distinct variants)." input CreateTransferRequestInput { "Optional caption." caption: String "The REQUESTING LogicalFacility id (the containment parent — the demand home)." requestingLogicalFacilityId: ID! "The optional TARGETED source LF; ABSENT = open to the group; must differ from the requesting LF." targetLogicalFacilityId: ID "Optional needed-by instant (UTC ISO-8601; BIRTH-FIXED — TR-k)." neededBy: String "Optional canned priority (low | normal | high | urgent; BIRTH-FIXED — TR-k)." priority: TransferRequestPriority "The lines (1..24 — TR-o)." lines: [TransferRequestLineInput!]! } "One accepted line: the request line (by lineNo) x the quantity this source commits NOW (cumulative live allocations never exceed requested — over-allocation refuses CONFLICT/DISCREPANCY, TR-g)." input AcceptTransferRequestLineInput { "The request line being accepted (1-based, as stored)." lineNo: Int! "The quantity accepted NOW — strictly positive." quantity: String! } "Accept-input for acceptTransferRequest: ONE acceptance = ONE linked Transfer born ready at the accepting source (a light pair births completed — the whole movement in the accept transaction)." input AcceptTransferRequestInput { "The TransferRequest id — tenant-scoped server-side." transferRequestId: ID! "The accepting SOURCE LogicalFacility id (!= the requesting LF; must match the target when the request is targeted — TR-g)." sourceLogicalFacilityId: ID! "Optional caption for the born Transfer (default: transfer lines)." caption: String "The accepted lines (min 1; at most one per request line)." lines: [AcceptTransferRequestLineInput!]! } "One declined line: the request line (by lineNo) x an optional informational reason." input RejectTransferRequestLineInput { "The request line being declined (1-based, as stored)." lineNo: Int! "Optional free-text reason (bounded; feeds the requester close-short judgment)." reason: String } "Reject-input for rejectTransferRequest: pure informational markers under the request OCC — no FSM move, no quantity effect, no reservation. ONE marker per (line, source); duplicates refuse." input RejectTransferRequestInput { "The TransferRequest id — tenant-scoped server-side." transferRequestId: ID! "The declining SOURCE LogicalFacility id (!= the requesting LF; must match the target when targeted)." sourceLogicalFacilityId: ID! "The declined lines (min 1; at most one per request line)." lines: [RejectTransferRequestLineInput!]! } "The acceptTransferRequest result: BOTH touched documents." type AcceptTransferRequestResult { "The TransferRequest AFTER the allocation rewrite (rollups + allocation rows stamped)." transferRequest: TransferRequest! "The linked Transfer born by this acceptance (ready — or completed for a light pair)." transfer: Transfer! } "Create-scope input: at most ONE location axis (whole-LF when both arrays are absent | zones | bins) plus the optional control-class II filter; members DISTINCT, scoped to the count's LF STATUS-FREE." input CountScopeInput { "Count these zones' bins (1..32 distinct members of the count's LF)." zoneIds: [ID!] "Count exactly these bins (1..32 distinct members of the count's LF)." binIds: [ID!] "Restrict the resolved IIs to ONE control class (non-controlled | lot-controlled | serially-controlled — the II attribute filter)." controlClass: String } "Create-input for createCount." input CreateCountInput { "Optional: when omitted the per-type default applies — ' count' (the line count is unknown at birth); when supplied it must be non-blank." caption: String "The LF being counted (the containment parent — rides parentId; scoped + ACTIVE at create)." logicalFacilityId: ID! "The canned count type (physical | cycle | spot — BIRTH-FIXED)." countType: CountType! "The scope selector; ABSENT = the whole LF (records + the un-binned pools)." scope: CountScopeInput "Optional recount linkage — must resolve to a POSTED Count at the SAME LF." recountOfCountId: ID } "One captured line: the resolved line (by lineNo) x the physically-counted quantity (>= 0 — an explicit ZERO is a legitimate capture; negatives refuse)." input CaptureCountLineInput { "The resolved line being captured (1-based, as stored at start)." lineNo: Int! "The counted quantity (decimal string, stock UoM; ZERO OR MORE)." countedQty: String! } "Capture-input for captureCount: the server point-reads each captured line's live on_hand and stamps {countedQty, expectedAtCapture, capturedAt} TOGETHER under the doc OCC. expectedAtCapture is SERVER-stamped — never caller-supplied." input CaptureCountInput { "The Count being captured — tenant-scoped server-side." countId: ID! "The captured lines (min 1; at most one per resolved line per call — merge duplicates)." lines: [CaptureCountLineInput!]! } "Create-input for createPurchaseOrder." input CreatePurchaseOrderInput { "Optional: when omitted the per-type default applies — 'purchase order line(s)'; when supplied it must be non-blank." caption: String "The supplying OrgVendor enablement — tenant-scoped + ACTIVE server-side; IMMUTABLE after birth (re-vendor = cancel + new). Its purchasingCurrency SNAPSHOTS as the PO currency (UNSET refuses NAMED — -i)." orgVendorId: ID! "Optional canned payment terms (registry tokens, e.g. net-30) — omitted ⇒ the OrgVendor's." paymentTerms: String "Optional canned Incoterms 2020 rule — omitted ⇒ the OrgVendor's." incotermCode: String "Optional vendor-side order/quote reference (max 64)." vendorReference: String "Optional free-text notes (max 4096)." notes: String "The lines (1..90 — the PER-CALL ceiling, distinct variant × receiving-LF keys; lineNo assigned 1..N in input order. A bigger order composes: create up to the per-call ceiling, then addPurchaseOrderLines up to 1000 lines on the document)." lines: [PurchaseOrderLineInput!]! } "One page of a PurchaseOrder's own line collection." type PurchaseOrderLinePage { "The page's records in lineNo order (a page may hold FEWER than `limit` — walk until `nextToken` is null)." items: [PurchaseOrderLine!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the line set is complete. Opaque + purchase-order-bound (the unfiltered lane) / filter-bound (the filtered lane)." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Append-input for addPurchaseOrderLines." input AddPurchaseOrderLinesInput { "The PurchaseOrder appended to — tenant-scoped + DRAFT (a live post-draft doc refuses CONFLICT/REF_STATE naming the required state)." purchaseOrderId: ID! "The appended lines (1..90 — the PER-CALL ceiling; the same defaults + gates as create; distinct variant × receiving-LF keys across the WHOLE document, not merely the call; the document's total refuses past 1000)." lines: [PurchaseOrderLineInput!]! } "Replace-input for updatePurchaseOrderLine." input UpdatePurchaseOrderLineInput { "The PurchaseOrder edited — tenant-scoped + DRAFT." purchaseOrderId: ID! "The line addressed by its stored lineNo (1..1000); a number with no live row refuses VALIDATION/INVALID naming it (removed numbers are never re-used, so the address is unambiguous forever)." lineNo: Int! "The replacement line — the same shape, defaults and gates as create; its lineNo is KEPT (the address does not move)." line: PurchaseOrderLineInput! } "Remove-input for removePurchaseOrderLines." input RemovePurchaseOrderLinesInput { "The PurchaseOrder edited — tenant-scoped + DRAFT." purchaseOrderId: ID! "The removed line numbers (1..90 per call, DISTINCT); an unknown number refuses VALIDATION/INVALID naming it." lineNos: [Int!]! } "Create-input for createReceipt." input CreateReceiptInput { "Optional: when omitted the per-type default applies — 'receipt line(s)'; when supplied it must be non-blank." caption: String "The parent PurchaseOrder (rides the HEADER parentId) — tenant-scoped server-side; must be RECEIVABLE (issued / acknowledged / partially_received — CONFLICT/REF_STATE else)." purchaseOrderId: ID! "The receiving LF this document captures arrivals for — tenant-scoped + ACTIVE; must be named by ≥1 PO line (VALIDATION/INVALID else)." logicalFacilityId: ID! "The lines (1..90 — the PER-CALL ceiling, each addresses a PO line destined to THIS LF; one line per (PO line × disposition); lineNo assigned 1..N in input order. A bigger arrival composes: create up to the per-call ceiling, then addReceiptLines up to 1000 lines on the document — the post WALKS, so the transaction budget no longer caps the document)." lines: [ReceiptLineInput!]! "Optional landed-cost ESTIMATE components (≤8, amounts in the PO currency — VALIDATION/INVALID naming both else)." landedComponents: [LandedCostComponentInput!] } "One page of a Receipt's own line collection." type ReceiptLinePage { "The page's records in lineNo order (a page may hold FEWER than `limit` — walk until `nextToken` is null)." items: [ReceiptLine!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the line set is complete. Opaque + receipt-bound (the unfiltered lane) / filter-bound (the filtered lane)." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Append-input for addReceiptLines." input AddReceiptLinesInput { "The Receipt appended to — tenant-scoped + DRAFT (a live post-draft doc refuses CONFLICT/REF_STATE naming the required state)." receiptId: ID! "The appended lines (1..90 — the PER-CALL ceiling; the same addressing + pack-entry gates as create against the birth-fixed parent PO; distinct (PO line × disposition) keys across the WHOLE document, not merely the call; the document's total refuses past 1000)." lines: [ReceiptLineInput!]! } "Replace-input for updateReceiptLine." input UpdateReceiptLineInput { "The Receipt edited — tenant-scoped + DRAFT." receiptId: ID! "The line addressed by its stored lineNo (1..1000); a number with no live row refuses NOT_FOUND naming it (removed numbers are never re-used, so the address is unambiguous forever)." lineNo: Int! "The replacement line — the same shape, defaults and gates as create; its lineNo is KEPT (the address does not move)." line: ReceiptLineInput! } "Remove-input for removeReceiptLines." input RemoveReceiptLinesInput { "The Receipt edited — tenant-scoped + DRAFT." receiptId: ID! "The removed line numbers (1..90 per call, DISTINCT); an unknown number refuses NOT_FOUND naming it." lineNos: [Int!]! } "Create-input for createRtv." input CreateRtvInput { "Optional: when omitted the per-type default applies — 'return to vendor line(s)'; when supplied it must be non-blank." caption: String "The OrgVendor enablement receiving the return (rides the HEADER parentId — lean 2) — tenant-scoped + ACTIVE server-side (an inactive enablement refuses NEW returns while in-flight docs keep transitioning)." orgVendorId: ID! "The OPTIONAL originating PurchaseOrder — must belong to the SAME OrgVendor and be past-issue (a draft/pending/cancelled order shipped nothing to return)." purchaseOrderId: ID "The LF the return ships FROM — tenant-scoped + ACTIVE + the buying org's (SL-b set-time; re-checked at ship)." shipFromLogicalFacilityId: ID! "Optional expected vendor credit (in the vendor purchasingCurrency — VALIDATION/INVALID naming both else); omitted ⇒ ship stamps the Σ quantity × CURRENT WMA default." expectedCredit: MoneyEntryInput "The lines (1..24 — the NAMED ceiling, -m; distinct variant × sourceBucket × bin keys; junctions resolved + stamped server-side)." lines: [RtvLineInput!]! } "Input for recordRtvCredit (shipped → credited — the manual-capture trigger of the OR-trigger pair)." input RecordRtvCreditInput { "The Rtv id — tenant-scoped server-side." rtvId: ID! "The credit the vendor actually issued — its currency must match the stored expectation when one exists." actualCredit: MoneyEntryInput! "Explicitly accept an actual ≠ expected credit (the mismatch otherwise refuses CONFLICT/CREDIT_MISMATCH, RETRYABLE — lean 6; the variance stays a reports-only fact)." acknowledgeVariance: Boolean } "Create-input for createVendorInvoice." input CreateVendorInvoiceInput { "Optional: when omitted the vendor invoice number IS the caption; when supplied it must be non-blank." caption: String "The PurchaseOrder this bill captures against (rides the HEADER parentId) — tenant-scoped + past-issue server-side (a draft/pending order was never sent; a cancelled one refuses)." purchaseOrderId: ID! "The BILLING OrgVendor — OPTIONAL (defaults to the PO vendor); a carrier/broker onboarded as its own OrgVendor names itself here. ACTIVE-gated." invoiceOrgVendorId: ID "The vendor own invoice number (raw spelling stored; trim+case-fold normalized for the double-pay UNIQ pair — a live holder refuses CONFLICT/IDENTITY_TAKEN naming it)." invoiceNumber: String! "The vendor invoice date (UTC ISO-8601 — their paper date)." invoiceDate: String! "The merchandise match lines (≤24, one per PO line) — at-least-one-of with actualComponents." matchLines: [VendorInvoiceMatchLineInput!] "The landed-cost ACTUAL components (≤8, amounts in the PO currency) — trued-up at capture against the posted receipts estimates of the same component type." actualComponents: [LandedCostComponentInput!] "Optional vendor-stated grand total (informational; in the PO currency)." total: MoneyEntryInput "Optional free-text notes (max 4096)." notes: String } "One derived inbound line. DERIVED at read — never stored (the TR outstanding stance)." type ExpectedReceipt { "The receivable PurchaseOrder (issued / acknowledged / partially_received)." purchaseOrderId: ID! "Its human handle (PO-… sysId)." purchaseOrderSysId: String! "The supplying OrgVendor enablement." orgVendorId: ID! "The buying org." organizationId: ID! "The PO line number." lineNo: Int! "The ordered variant." variantId: ID! "The receiving LF the outstanding quantity is inbound to." logicalFacilityId: ID! "ordered − received (DERIVED; strictly positive rows only — fully-received lines drop)." outstandingQty: String! "The line expected-arrival instant (UTC ISO-8601; absent when never derivable)." expectedArrivalAt: String } "One issue-time line selection — the (orderLineNo, quantity) entry." input InvoiceLineSelectionInput { "The order line to invoice (its frozen 1-based lineNo)." orderLineNo: Int! "The quantity to invoice (positive decimal string; ≤ the line's un-invoiced remainder)." quantity: String! } "Issue-input for issueInvoice." input IssueInvoiceInput { "Optional: when omitted the default is 'invoice of N lines'; when supplied it must be non-blank." caption: String "The Order to invoice — same-group; ∈ {placed, completed} (an open/held cart cannot bill; a voided/abandoned/cancelled order has nothing to bill)." orderId: ID! "The partial-model selections (omitted = the FULL un-invoiced remainder; supplied = ≥ 1 entries, distinct orderLineNos)." lines: [InvoiceLineSelectionInput!] } "One note delta entry — a positive MAGNITUDE on the invoice line's taxableBase axis; the SIGN is the document's (CreditNote −, DebitNote +); the tax delta recomputes on top from the CAPTURED components." input NoteDeltaLineInput { "The invoice line to correct (1-based on the superseded Invoice)." invoiceLineNo: Int! "The base-delta magnitude in minor units (strictly positive)." amountMinor: Int! } "Issue-input for issueCreditNote." input IssueCreditNoteInput { "Optional: when omitted the default is 'credit note of '; when supplied it must be non-blank." caption: String "The superseded Invoice — same-group; ∈ {issued, closed} (a voided invoice refuses)." invoiceId: ID! "The REQUIRED audit reason." reason: String! "The positive delta magnitudes, one per corrected invoice line (≥ 1, distinct invoiceLineNos)." lines: [NoteDeltaLineInput!]! } "Issue-input for issueDebitNote." input IssueDebitNoteInput { "Optional: when omitted the default is 'debit note of '; when supplied it must be non-blank." caption: String "The superseded Invoice — same-group; ∈ {issued, closed} (a voided invoice refuses)." invoiceId: ID! "The REQUIRED audit reason." reason: String! "The positive delta magnitudes, one per corrected invoice line (≥ 1, distinct invoiceLineNos)." lines: [NoteDeltaLineInput!]! } "One receive-time disposition entry — addresses a RETURN line by lineNo; one entry per (lineNo, disposition) pair; Σ per non-stockless line == the line quantity EXACTLY (exact cover; stockless lines take NO entries)." input ReturnDispositionEntryInput { "The RETURN line this entry covers (its 1-based lineNo)." lineNo: Int! disposition: ReturnDisposition! "The quantity under this code (positive decimal string)." quantity: String! "REQUIRED for non-restock codes." reason: String } "Receive-input for receiveReturn." input ReceiveReturnInput { returnId: ID! "The doc revision the caller read." expectedRevision: ID! "The disposition cover (≥ 1 entries)." dispositions: [ReturnDispositionEntryInput!]! } "Refund-input for refundReturn." input RefundReturnInput { returnId: ID! "The doc revision the caller read." expectedRevision: ID! "The routing method: cash reaches the drawer; original_tender walks the reversible money LIFO — instrument redemptions reverse INTERNALLY, integrated payments through the processor; store_credit MINTS a customer-bound instrument." method: ReturnRefundMethod! "Optional external reference (a processor id / credit-slip number)." reference: String "The OPEN drawer session paying out — REQUIRED for method=cash, REFUSED otherwise." tillSessionId: ID "The store-credit customer binding: this block ∥ the Return's order-capture copy; absent BOTH, the mint refuses VALIDATION/INVALID naming it." customer: OrderCustomerInput } "The wire-recordable MANUAL drawer entry types: float_in/count_adjust are open/close-posted; cash_sale/cash_refund/change_given post ONLY through the tender writers (applyTender/refundTender/the Return refund writers)." enum ManualCashEntryType { paid_in paid_out drop pickup } "Open-input for openTillSession: the Register (tenant-scoped, ACTIVE) + the counted opening float (1..8 distinct currencies, each >= 0 — a zero is an explicit statement and posts NO float_in entry). openedBy stamps server-side from the principal." input OpenTillSessionInput { "Optional: when omitted the default applies — 'till session at '; non-blank when supplied." caption: String registerId: ID! "The counted opening float per currency (distinct; >= 0 each)." float: [DrawerAmountInput!]! } "Close-input for closeTillSession: the counted drawer per currency (distinct; >= 0). The COVERING RULE: every currency with a non-zero drawer total MUST be counted (state the zero — an uncounted one refuses VALIDATION naming it); counting an unledgered currency is LEGAL (pure over)." input CloseTillSessionInput { tillSessionId: ID! "The doc revision the caller read." expectedRevision: ID! "The counted drawer (may be empty ONLY when every drawer total is zero)." counted: [DrawerAmountInput!]! } "Record-input for recordCashEntry: a POSITIVE magnitude (the port stamps the type-law sign — paid_in/pickup INTO the drawer, paid_out/drop OUT); reason REQUIRED; glCategory REQUIRED on paid_in/paid_out and refused otherwise. The session must be open." input RecordCashEntryInput { tillSessionId: ID! entryType: ManualCashEntryType! "The entry currency (the per-currency drawer)." currency: String! "The POSITIVE magnitude in minor units — the port stamps the sign." amountMinor: Int! "REQUIRED — the merchant's drawer-op reason ('window cleaner', 'safe drop 14:00')." reason: String! "The GL category — REQUIRED iff paid_in/paid_out; a bounded free string (the GAAP journal mapping is a named deferral)." glCategory: String "Optional caption override." caption: String "Provenance document refs (bounded free strings)." refs: [String!] } "The external_card capture input — a card authorized on a THIRD-PARTY pinpad, recorded: brand + authNumber REQUIRED (strict); NO Stripe Payment, NO processor call." input TenderExternalCardInput { brand: String! last4: String deviceRef: String authNumber: String! } "The integrated-card presentation input: the OPAQUE tokenized payment method the processor will charge (Stripe pm_… class — Stripe.js/Terminal hold the PAN; a raw card-number shape refuses at the boundary, PCI). Brand/last4 are NOT accepted — the stored truth comes from the processor ACK." input TenderCardInput { methodRef: String! } "No further notes." input TenderInstrumentInput { instrumentId: ID code: String } "Apply-input for applyTender: collectedMinor = the cash physically handed over (BEFORE change, tip included) or the externally-authorized amount. cash REQUIRES the open till session and REFUSES the capture block; external_card the exact mirror; foreign_cash names the tendered currency (collectedCurrency — collectedMinor is in ITS minor units), REQUIRES the till, is converted at OUR stored BUY rate (settle + change in the org default currency; no covering rate = CONFLICT/NO_EFFECTIVE_RATE, retryable), and carries no tip (a named deferral). Dormant types refuse VALIDATION/UNSUPPORTED naming their arrival." input ApplyTenderInput { orderId: ID! "The Order revision the caller read." expectedRevision: ID! tenderType: TenderType! "The POSITIVE physical/authorized amount in minor units." collectedMinor: Int! "The TENDERED currency — REQUIRED iff foreign_cash, REFUSED otherwise." collectedCurrency: String "The tip portion of collectedMinor. REFUSED on foreign_cash." tipMinor: Int "The OPEN drawer session — REQUIRED for cash/foreign_cash, REFUSED otherwise." tillSessionId: ID "The pinpad capture — REQUIRED for external_card, REFUSED otherwise." externalCard: TenderExternalCardInput "The tokenized method presentation — REQUIRED for card, REFUSED otherwise." card: TenderCardInput "The instrument presentation — REQUIRED for gift_card/gift_certificate/store_credit, REFUSED otherwise. The redeem lane: active-only · type⟺tender · same-currency · ≤ the remaining due (NO change — the no-cash-out strict default) · ≤ the balance (CONFLICT/INSUFFICIENT_BALANCE — exhaust exactly + split-tender the remainder); NO tip; NO tillSessionId (no drawer money)." instrument: TenderInstrumentInput "Optional — why this tender (at most 256 characters). When the tender charges a house account (on_account) the reason is recorded on that ledger too — at most 256 characters there." reason: String "Optional caption override." caption: String "Provenance document refs (bounded free strings)." refs: [String!] } "Refund-input for refundTender: a POSITIVE magnitude (the port stamps the negative sign); cap = the net tendered (CONFLICT/OVER_TENDERED); cash is live; the stored-value types joined." input RefundTenderInput { orderId: ID! "The Order revision the caller read." expectedRevision: ID! "cash + the stored-value types are live; card refunds ride the processor path; recorded external-card refunds ride the Return lane." tenderType: TenderType! "The POSITIVE magnitude to refund in minor units." amountMinor: Int! "The OPEN drawer session paying out — REQUIRED for cash, REFUSED otherwise." tillSessionId: ID "The EXPLICIT instrument refund target — REQUIRED for stored-value types, REFUSED otherwise: a refund_reversal credits it in ONE transaction; a depleted target RE-OPENS (system:refund_credit); doomed/inactive refuse CONFLICT/REF_STATE." instrument: TenderInstrumentInput "REQUIRED — money leaves the business (at most 256 characters). When the refund credits a house account (on_account) the reason is recorded on that ledger too — at most 256 characters there." reason: String! caption: String refs: [String!] } "Input for processReaderPayment: the READER is NEVER named here — it resolves from the CALLER'S DEVICE SESSION (the composite-POS law: exactly ONE active registered card reader on the paired device). amountMinor = the portion APPLIED toward the order balance (≤ the remainder EXACTLY); tipMinor charges ON TOP. The op returns the CREATED Payment and the reader takes over — poll the payment record: the processor confirm commits the tender + the authorize flip; a reader decline lands it failed." input ProcessReaderPaymentInput { orderId: ID! "The Order revision the caller read." expectedRevision: ID! "The amount APPLIED toward the order balance in minor units (≤ the remainder EXACTLY — the applyTender card law)." amountMinor: Int! "The tip charged ON TOP of amountMinor." tipMinor: Int reason: String "Optional caption override." caption: String "Provenance document refs (bounded free strings)." refs: [String!] } "No-sale input: open the drawer WITHOUT a sale; moves NO money — the write is the noSaleCount/lastNoSaleAt stamp (the audit/fraud feed reads the stream)." input NoSaleInput { tillSessionId: ID! "The doc revision the caller read." expectedRevision: ID! "REQUIRED — why the drawer opened without a sale ('change for a customer')." reason: String! } "The posReturn refund routing." input PosReturnRefundInput { method: ReturnRefundMethod! reference: String "REQUIRED for method=cash (the drawer paying out), REFUSED otherwise." tillSessionId: ID } "One-shot input for posReturn: the NewReturn essentials + the receive disposition cover + the refund routing, walked requested→approved→received→refunded in ONE call." input PosReturnInput { "Optional." caption: String "The Order being returned against — same-group; placed or completed." orderId: ID! "Optional Invoice ref — must belong to orderId (the receipted-return audit edge)." invoiceId: ID "The processing/receiving LF — becomes the parent." logicalFacilityId: ID! "The returned lines (1..45, distinct orderLineNos — the ReturnLineInput shape verbatim)." lines: [ReturnLineInput!]! "The receive cover." dispositions: [ReturnDispositionEntryInput!]! refund: PosReturnRefundInput! } "Copy-input for copyCannedRole: the template key + an optional caption override; the compiled v-pinned descriptors + the authorityTier + the provenance stamps (templateKey/templateVersion) copy PORT-SIDE — customize AFTER the copy via updateRole. A copy NEVER auto-revs when the template does (fork semantics)." input CopyCannedRoleInput { "The canned template key (cannedRoles lists the 7)." key: RoleTemplateKey! "Optional caption override." caption: String } "Request-input for requestApproval: a LIVE gated action + its target + the parent coordinate (tillSessionId XOR logicalFacilityId) + the REQUIRED reason. requiredTier/expiresAt derive SERVER-side; the fingerprint marker mints in the create transaction (ONE live request per (target, action) — a duplicate refuses CONFLICT/REFERENCED naming the holder)." input RequestApprovalInput { "The gated action (dotted canonical name — registry; LIVE (the contracts LIVE_GATED_ACTIONS roster, verbatim): discount.apply | void.transaction | return.approve | no_sale | refund.routing_exception | credit.over_limit | order.below_minimum; a dormant action refuses VALIDATION/UNSUPPORTED naming its arrival)." action: String! "The blocked action's target — the construct the action gates (the contracts GATED_ACTION_TARGETS: Order · Return · TillSession; tenant-scoped server-side); state-gated to WHERE the action's op fires (an un-voidable order, a closed till, an unreceived return refuse CONFLICT/REF_STATE — an approval never revives a window)." targetId: ID! "The bound value (integer minor units) — REQUIRED for discount.apply (the EXACT-match fingerprint coordinate); refused for whole-target actions." valueMinor: Int "The OPEN TillSession the action runs in (the parent; XOR logicalFacilityId)." tillSessionId: ID "The ACTIVE LF the action runs at when no till session is involved (XOR tillSessionId)." logicalFacilityId: ID "Why the requester needs the override." reason: String! "Optional caption override." caption: String } "Ship-input for shipFulfillment: an EFFECTIVE ship-to is required (stored at create or supplied here — the payload REPLACES as the label truth); carrier/tracking are capture-only." input ShipFulfillmentInput { fulfillmentId: ID! "The doc revision the caller read." expectedRevision: ID! "The late/replacing ship-to capture (required here iff none stored)." shipTo: FulfillmentShipToInput "The carrier name capture." carrierName: String "The tracking reference capture." trackingRef: String } "Evidence-input for submitEvidenceDispute: ONE free-text field (the minimal-strict surface — maps to the processor's uncategorized_text evidence slot; structured evidence fields are deferred growth)." input SubmitEvidenceDisputeInput { disputeId: ID! "The doc revision the caller read." expectedRevision: ID! "The evidence free text (1..4000; submitted VERBATIM with submit=true — the processor adjudicates)." evidenceText: String! } "Activate-input for activateStoredValueInstrument: the issued load + the required reason ride the flip." input ActivateStoredValueInstrumentInput { instrumentId: ID! "The instrument revision the caller read." expectedRevision: ID! "The value the activation ISSUES (≥ 1 — an instrument never activates empty)." amountMinor: Int! "REQUIRED — money is born; at most 256 characters — it is recorded on the issue entry." reason: String! } "Schedule-input for scheduleMarkdownPlan." input ScheduleMarkdownPlanInput { planId: ID! "The plan revision the caller read." expectedRevision: ID! "Optional narration — rides the transition events." reason: String } "Cancel-input for cancelMarkdownPlan." input CancelMarkdownPlanInput { planId: ID! "The plan revision the caller read." expectedRevision: ID! "Optional narration — rides the transition events + the doomed records' causes." reason: String } "Pay-input for arPay. No caller OCC — the conditioned frontier premise IS the concurrency truth (the hot-money class)." input ArPayInput { "The OrgCustomer house account (tenant-scoped server-side)." orgCustomerId: ID! "The POSITIVE payment magnitude in minor units (the account's arCurrency lane; > the balance refuses CONFLICT/INSUFFICIENT_AR_BALANCE naming live figures)." amountMinor: Int! "Optional narration (a cheque reference)." reason: String } "Writeoff-input for arWriteoff." input ArWriteoffInput { orgCustomerId: ID! "The POSITIVE writeoff magnitude in minor units (≤ the balance — the never-negative law)." amountMinor: Int! "REQUIRED — bad debt always says why." reason: String! } "Settle-input for settleCreditNoteToAr." input SettleCreditNoteToArInput { creditNoteId: ID! "The note revision the caller read." expectedRevision: ID! "Optional narration — rides the close transition + the entry." reason: String } "Settle-input for settleDebitNoteToAr." input SettleDebitNoteToArInput { debitNoteId: ID! "The note revision the caller read." expectedRevision: ID! reason: String } "Reorder-input for reorderOrder: the sale-profile NON-DOOMED source + OPTIONAL context overrides. No source OCC — the source is READ, never written." input ReorderOrderInput { "The source Order (tenant-scoped): sale-profile only (a draft/quote converts via accept; other profiles refuse VALIDATION/UNSUPPORTED) + non-doomed (cancelled/voided/abandoned refuse CONFLICT/REF_STATE naming the state)." orderId: ID! "Override the selling org (default: the source's) — ACTIVE-gated; the clone currency snapshots the EFFECTIVE org's defaultCurrency." organizationId: ID "Override the selling/fulfilling LF (default: the source's) — ACTIVE + must belong to the effective org (the spine law)." logicalFacilityId: ID "Override the selling channel (default: the source's) — decides the clone's parent (pos → the LF; ecom → the org) + the reserve arm at place." channel: OrderChannel } "Copy-input for copyCannedConsentPurpose: the template key + an optional caption override; the code + consentModel + the provenance stamps (templateKey/templateVersion) copy PORT-SIDE — customize AFTER the copy via updateConsentPurpose (⚠ consentModel stays birth-fixed on the copy too). A copy NEVER auto-revs when the registry does (fork semantics)." input CopyCannedConsentPurposeInput { "The canned template key (cannedConsentPurposes lists the 6)." key: ConsentPurposeTemplateKey! "Optional caption override." caption: String } "STAFF decide-input for grantConsent/withdrawConsent: the acted-on consumer is NAMED and the capture surface is REQUIRED." input ConsentDecisionInput { "The acted-on Consumer (tenant-scoped; NOT doomed — an erased subject takes no decisions; ⚠ a SUSPENDED consumer stays LEGAL here: consent is the data subject's right, independent of the merchant hold)." consumerId: ID! "The ConsentPurpose decided on (tenant-scoped + ACTIVE — a retired purpose refuses CONFLICT/REF_STATE naming it)." purposeId: ID! "The consent-notice/policy version PRESENTED at this decision (1..128 — REQUIRED caller data; a Policy/notice CONSTRUCT is the named deferral)." policyVersion: String! "WHERE the decision was captured — storefront | pos | back_office | cli | import (REQUIRED — no default)." captureSurface: String! "The locale PRESENTED (canonical BCP-47 core); optional." captureLocale: String } "CONSUMER decide-input for grantMyConsent/withdrawMyConsent: the principal's OWN consumerId + the SERVER-FIXED storefront captureSurface stamp kit-side." input MyConsentDecisionInput { "The ConsentPurpose decided on (tenant-scoped + ACTIVE)." purposeId: ID! "The consent-notice/policy version PRESENTED (1..128)." policyVersion: String! "The locale presented (canonical BCP-47 core); optional." captureLocale: String } "One CS-case thread message. internal_note rows NEVER serialize to the consumer face (ruling — the structural walk filter)." type CaseMessage { id: ID! type: String! caption: String! "active (a posted fact) — the void lane is FSM data with NO wire op (the AREntry class)." status: String! "The owning CsCase." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "consumer | user | system — WHO wrote it (system rows carry NO authorId; the future auto_close trail)." authorKind: String! "The authoring principal (a Consumer or User id — server-stamped from the channel); absent on system rows." authorId: ID "customer_visible | internal_note — internal notes are staff-face ONLY (ruling)." visibility: String! "The message body (1..4096)." body: String! } "One page of a case's thread." type CaseMessagePage { items: [CaseMessage!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the thread is complete. Opaque + case-bound." nextToken: String } "STAFF append-input for addCaseMessage: visibility is the staff author's CHOICE; the author stamps server-side." input NewCaseMessageInput { "The case appended to (tenant-scoped; a terminal case refuses CONFLICT/IMMUTABLE)." caseId: ID! "The message body (1..4096)." body: String! "customer_visible | internal_note (ruling — an internal note never crosses the consumer face)." visibility: String! } "CONSUMER case-open input for openMyCase." input OpenMyCaseInput { "The subject line (REQUIRED — an unnamed case is meaningless)." caption: String! "return_request | refund_inquiry | product_issue | complaint | general_inquiry | warranty_claim | shipping_issue | order_change | other." caseType: String! "The opening message body (REQUIRED, 1..4096 — the narrative spine, ruling)." body: String! "Optional OWN-order ref — must trace to the caller (cross-owner refuses NOT_FOUND, no leak)." orderId: ID "Optional OWN-return ref — same ownership law." returnId: ID } "CONSUMER reply-input for addMyCaseMessage." input NewMyCaseMessageInput { "The caller's OWN case (cross-owner refuses NOT_FOUND)." caseId: ID! "The message body (1..4096)." body: String! } "CONSUMER RMA-input for requestMyReturn." input RequestMyReturnInput { "The caller's OWN Order (explicit id — order browse is the storefront; cross-owner refuses NOT_FOUND)." orderId: ID! "The returned lines (≥ 1, distinct orderLineNos, positive quantities — the ReturnLineInput shape verbatim)." lines: [ReturnLineInput!]! } "One desired variant on a GiftRegistry. variantId is the membership identity (IMMUTABLE — remove + re-add instead); REMOVE = doom, history preserved (re-adding TAKES OVER the doomed marker — ruling)." type RegistryItem { id: ID! type: String! caption: String! "active | doomed (REMOVED — history; the marker frees by takeover)." status: String! "The owning GiftRegistry." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "The desired Variant. IMMUTABLE." variantId: ID! "1..999." desiredQty: Int! "low | normal | high — the owner's signal to gift-givers (optional)." priority: String "The owner's note (1..512, optional)." note: String } "One page of a registry's item rows." type RegistryItemPage { items: [RegistryItem!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the list is complete. Opaque + registry-bound." nextToken: String } "One recorded purchase against a registry item. Purchased qty per item = Σ these rows' qty; remaining = max(0, desired − purchased) — OVER-fulfillment records legally (ruling: facts over gates)." type RegistryFulfillment { id: ID! type: String! caption: String! "active (a posted fact) — the void lane is FSM data with NO wire op (corrections = deferral 11)." status: String! "The owning GiftRegistry." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "The fulfilled RegistryItem (its row id — validated ACTIVE in THIS registry at record)." registryItemId: ID! "The fulfilling Order (ref-only — NO order amendment)." orderId: ID! "The fulfilling order line." orderLineNo: Int! "1..999." qty: Int! "The gift-giver when a registered Consumer (guest purchasers absent)." purchaserConsumerId: ID } "One page of a registry's fulfillment facts." type RegistryFulfillmentPage { items: [RegistryFulfillment!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the list is complete." nextToken: String } "Item ADD input — SHARED by both lanes. The (registry × variant) marker mints in the SAME transaction; the registry must be ACTIVE (ruling); the ACTIVE-items ceiling (200) gates kit-side." input NewRegistryItemInput { "The target registry (tenant-scoped; the consumer lane requires OWNERSHIP — cross-owner refuses NOT_FOUND)." registryId: ID! "The desired Variant (in-tenant + ACTIVE)." variantId: ID! "1..999." desiredQty: Int! "low | normal | high." priority: String "1..512." note: String } "Item EDIT input — SHARED by both lanes (≥1 payload field). ⚠ variantId is DELIBERATELY absent — the membership identity (remove + re-add instead, the CollectionMember law)." input EditRegistryItemInput { registryId: ID! itemId: ID! desiredQty: Int priority: String note: String } "Fulfillment RECORD input." input RecordRegistryFulfillmentInput { registryId: ID! registryItemId: ID! orderId: ID! "The fulfilling order line (the fact names its line)." orderLineNo: Int! "1..999." qty: Int! "The gift-giver when a registered Consumer (optional)." purchaserConsumerId: ID } "CONSUMER registry-open input for createMyGiftRegistry." input CreateMyGiftRegistryInput { "The registry name (REQUIRED — an unnamed registry is meaningless)." caption: String! "wedding | baby | birthday | anniversary | holiday | wishlist | custom." registryType: String! "public | unlisted | private — defaults 'private' (strict; structurally dormant until, ruling)." privacy: String "ISO-8601 instant — present ⇒ arms the scheduled expiry (ruling)." eventDate: String shipTo: RegistryShipToInput } "CONSUMER review-submit input for submitMyReview." input SubmitMyReviewInput { "The reviewed Product (in-tenant + non-doomed)." productId: ID! "1..5 (integer)." rating: Int! "1..200." title: String! "1..4096." body: String! "No further notes." orderId: ID } "CONSUMER review-edit input for updateMyReview. ⚠ productId is DELIBERATELY absent (the marker identity — re-target = a NEW review after removal); supplying orderId RE-RUNS the pointed proof; the STATE never moves on edit." input EditMyReviewInput { "The author's OWN review (cross-author refuses NOT_FOUND)." reviewId: ID! rating: Int title: String body: String "Re-runs the pointed proof (ruling — re-derivation on edit)." orderId: ID } "One platform token-ledger fact. The wallet's balance = Σ these rows' signed amounts EXACTLY — cached in the SAME transaction as every append (ruling: the ledger never lies — drawdowns record IN FULL and the balance may transiently dip below zero; the floor is the exhaustion CASCADE, never entry-clamping)." type TokenEntry { id: ID! type: String! caption: String! "active (a posted fact) — the void lane is FSM data with NO wire op (corrections are authority adjustment entries)." status: String! "The owning TokenAccount." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "purchase | plan_included | grant | drawdown | transfer | adjustment (the registry roster VERBATIM — NO refund, NO expiry; plan_included = the monthly fee's beyond-overhead share auto-credited at settle — banks forever, fungible with purchases)." entryKind: String! "The SIGNED integer token amount — the sign IS the flow direction (purchase/grant +, drawdown −, transfer ±, adjustment ±)." amountTokens: Int! "The reason text — always present on grant/adjustment (root money moves say why); optional narration otherwise." reason: String "The settled TokenPurchase." tokenPurchaseId: ID "The BillingCharge whose settle minted this credit." billingChargeId: ID "The transfer counterpart's org group." transferCounterpartRootId: ID "The transfer counterpart's entry (the sum-conserving pair cross-reference — transfer entries only)." transferCounterpartEntryId: ID "The per-(event × dimension) itemization (drawdown entries only — the transparency law; ruling: each line names ITS usage event)." drawdownLines: [TokenDrawdownLine!] "The µtoken accrual carried INTO this entry from prior sub-token usage." carriedInMicroTokens: Int "The µtoken remainder carried OUT to the wallet's microTokenCarry after this entry materialized." carriedOutMicroTokens: Int "The rate card that priced this entry." rateCardVersion: Int } "One drawdown line — the per-(event × dimension) itemization." type TokenDrawdownLine { "The rated usage event's id." usageEventId: ID! "records_storage | blob_storage | archived_blob_storage | compute | bandwidth_in | bandwidth_out | api_call (SPEC_REGISTRY row 124 — cloud-neutral)." dimension: String! "The measured quantity in the dimension's declared unit (integer)." quantity: Int! "The line's micro-token product (quantity × the card rate; 1,000,000 micro-tokens = 1 token)." microTokens: Int! } "One page of a wallet's token-ledger facts." type TokenEntryPage { items: [TokenEntry!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the ledger is walked to the wallet's birth month. Opaque + wallet-bound." nextToken: String } "One platform referral-earnings fact. accrue (+, the SUBSCRIPTION line — 20% of each referred group's collected base-fee overhead, LIFETIME both-in-good-standing) · usage (+, the CONSUMPTION line — 10% of the referred group's monthly consumed paid-kernel value, its first 12 billed months) · applied (−, bill-netting — YOUR OWN base fee credit-settled against earnings) · clawback (−, a dispute reversal). Each entry snapshots its rate + basis (self-auditing at every parse)." type AffiliateAccrual { id: ID! type: String! caption: String! "active (a posted fact) — the void lane is FSM data with NO wire op." status: String! "The paying group's TokenAccount (the driving fact's own anchor — YOUR wallet on applied entries)." parentId: ID! "The PAYING org group." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "accrue | usage | applied | clawback." entryType: String! "The EARNING org group." ownerOrgGroupId: ID! "The entry's month (YYYY-MM — the collected/consumed/netted period)." periodMonth: String! "accrue only: the referred group's billed-cycle ordinal (1-based — LIFETIME)." cycle: Int "The rate that applied (percent — the two EARNING lines; snapshotted, the entry never lies)." ratePercent: Int "accrue only: the ACCRUAL BASIS in USD cents." collectedUsdCents: Int "usage only: the month's consumed paid-kernel VALUE this entry commissions (USD cents — exact per-block prices)." usageBasisCents: Int "The figure, USD cents — SIGNED by type: accrue/usage strictly positive · applied/clawback strictly negative." amountUsdCents: Int! "accrue only: the driving BillingCharge. Absent on a CREDIT-SETTLED cycle's accrue (no charge document exists — the payer's own applied entry is the netting's trail)." billingChargeId: ID } "One kernel block — a settled purchase's STOCK lifecycle. Blocks consume OLDEST-FIRST with at most ONE open at a time; a block EARMARKED for transfer freezes until the decision (it cannot be consumed — freezing most of your stock can starve the wallet, the disclosed strictness); an OPENED block can never transfer (the purity law); a transferred block records where it went." type KernelBlock { "== the funding TokenPurchase id (one id, two records)." id: ID! type: String! caption: String! "allocated (charge in flight) · approved (money settled — in the queue; transferable) · opened (being consumed — transfer-ineligible forever) · consumed (none left) · transfer_requested (frozen, awaiting the decision) · transfer_denied (stock again — consumable, re-requestable) · transfer_approved (frozen — execute or lapse) · transferred (moved whole) · doomed (the charge failed)." status: String! "The group wallet (the queue's operational home)." parentId: ID! rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "The block's whole size (kernels/tokens — blocks move WHOLE)." tokensPurchased: Int! "What the block cost (USD cents — its own consumption is valued at exactly this, proportionally)." usdAmountCents: Int! "The volume tier that priced it." volumeTierCode: String! "When the money settled (absent = not yet stock / the charge failed)." approvedAt: String "When the queue first reached it (present ⇒ it can never transfer — the purity law)." openedAt: String "When it fully drained." consumedAt: String "The LATEST transfer ask (re-asks refresh it)." transferRequestedAt: String "The requested destination group." transferRequestedToOrgGroupId: ID "Your request's reason (rides the review)." transferRequestReason: String "The LATEST deny + the reviewed reason (a denied block is stock again)." transferDeniedAt: String transferDeniedReason: String "Where it went (present ⟺ transferred)." transferredToOrgGroupId: ID transferredAt: String } "Your group's claimed referral code." type ClaimedReferralCode { "The shareable code (give it to businesses you refer — they enter it at signup)." code: String! "What the referred business gets: this percent off their monthly base fee…" promotionPercent: Int! "…for this many billing cycles (the two-sided standard)." promotionCycles: Int! } "One Stripe revshare give-back entry. ONE entry per CLOSED month PER positive-net currency where the group's earned tier stood (the per-currency basis — no cross-currency math ever); every figure is snapshotted (self-auditing — amountMinor == the half-up volume × rateBps × tierBp product at every parse)." type GiveBackAccrualEntry { id: ID! type: String! caption: String! "active (a posted fact) — the void lane is FSM data with NO wire op." status: String! "The group's TokenAccount (the wallet anchor)." parentId: ID! "The earning org group — the reader's own." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "accrue (the v1 roster VERBATIM — clawback/adjust arrive with the payout lane, worded)." entryType: String! "The CLOSED month the entry pays back (YYYY-MM)." periodMonth: String! "REAL consecutive good-standing months at the evaluation." tenureMonths: Int! "Tenure + any switcher clock credit — what the ladder read." effectiveTenureMonths: Int! "ladder | heritage (the flat-100% GEN-convert rule)." basis: String! "The earned share, basis points (2500 · 5000 · 7500 · 10000)." tierBp: Int! "The revshare rate that applied, basis points of volume (snapshotted — the config is adjustable, the entry never lies)." rateBps: Int! "The give-back config version in force at the mint." rateVersion: Int! "The entry's currency — the netted volume's own (one entry per positive-net currency)." currency: String! "The NET basis the entry pays on (the month's settled volume − refund netting + any consumed carry), minor units." volumeMinor: Int! "The accrued figure in the entry's currency, minor units — STRICTLY positive (the zero-skip law)." amountMinor: Int! } "One lifetime give-back total." type GiveBackLifetimeTotal { currency: String! "Σ every accrued entry in this currency, minor units." amountMinor: Int! } "The caller group's give-back standing (the program's merchant-visible transparency surface): the derived tenure clock, the earned tier, the next rung, and the earned ledger. Figures are as of computedThroughMonth — the last CLOSED month the billing engine decided." type GiveBackReport { "No further notes." convertedFrom: String "No further notes." revokedAt: String "The root’s spoken revocation reason (at most 256 characters; present with revokedAt)." revokedReason: String "REAL consecutive good-standing months (0 = no live streak / nothing evaluated yet)." tenureMonths: Int! "Tenure + any switcher clock credit — what the ladder reads." effectiveTenureMonths: Int! "ladder | heritage — how the current tier is earned." basis: String! "The earned share NOW, basis points (0 = not yet earning)." tierBp: Int! "The next ladder rung above the current effective months (absent at the top and for a standing heritage 100%)." nextTierAtMonths: Int nextTierBp: Int "The last CLOSED month the engine decided (absent = no month ever evaluated)." computedThroughMonth: String "Σ every accrued entry PER CURRENCY, minor units, currency-ascending." lifetime: [GiveBackLifetimeTotal!]! "The earned entries, NEWEST-FIRST + bounded (limit clamps [1,200] default 50; before pages backward by entry id)." accruals: [GiveBackAccrualEntry!]! } "One referred signup on YOUR referral code and where it stands." type ReferredSignup { "The referred org group (the business that signed up with your code — its own group id, the same handle it shares for kernel-block transfers)." referredOrgGroupId: ID! "The referred group's code (its merchant handle). Null when the group no longer exists." referredGroupCode: String "pending (awaiting AlmondTill's approval) | approved (earning from their next billing cycle) | denied (this referral will not earn — their own discount stands). Null when the group no longer exists. Derived from the referred group's own standing — never stored on the roster row." standing: String "When the referred group was born on your code (UTC ISO-8601) — the review clock starts here; pending-era months never retro-accrue." createdAt: String! "The decision instant (UTC ISO-8601); null while pending." decidedAt: String } "How one referred business is performing for you: the roster row's fields VERBATIM (the ReferredSignup shape) plus what its months have earned you." type ReferralPerformance { "The referred org group (the business that signed up with your code)." referredOrgGroupId: ID! "The referred group's code (its merchant handle). Null when the group no longer exists." referredGroupCode: String "pending | approved | denied — derived from the referred group's own standing; null when the group no longer exists." standing: String "When the referred group was born on your code (UTC ISO-8601)." createdAt: String! "The decision instant (UTC ISO-8601); null while pending." decidedAt: String "Line-1 months that paid you — one accrue entry each (the subscription share; LIFETIME while both groups stand)." cyclesEarned: Int! "The referred group's billed-cycle ordinal at its LAST line-1 mint (1-based). Null before the first mint." latestCycle: Int "Line-2 months that paid you — one usage entry each (the consumption share inside the referred group's first 12 billed months; a month with no paid consumption mints nothing and still spends a window month)." usageMonthsEarned: Int! "Billed months left in the usage window AS OF the last line-1 mint (12 − latestCycle, floored at 0). Null before the first mint." usageMonthsLeft: Int "What this business earned you, lifetime (accrue + usage; USD cents, ≥ 0)." earnedUsdCents: Int! "Dispute reversals traced to this business (USD cents, ≤ 0)." clawbackUsdCents: Int! "The first month (YYYY-MM) an earning entry landed for this business; null before the first." firstEarnedMonth: String "The last month (YYYY-MM) an earning entry landed for this business; null before the first." lastEarnedMonth: String } "One month of your referral earnings: the four entry types summed for that period, the net, and how many referred businesses earned that month." type ReferralMonth { "The period, UTC YYYY-MM." periodMonth: String! "Σ accrue that month (the subscription share; ≥ 0)." accrueUsdCents: Int! "Σ usage that month (the consumption share; ≥ 0)." usageUsdCents: Int! "Σ applied that month (your own base fee credit-settled from earnings; ≤ 0)." appliedUsdCents: Int! "Σ clawback that month (dispute reversals; ≤ 0)." clawbackUsdCents: Int! "The four summed (SIGNED)." netUsdCents: Int! "Distinct referred businesses with an earning entry that month." earningReferrals: Int! } "Your referral program at a glance: counts by standing, lifetime totals by kind (SIGNED like the ledger: earned ≥ 0 · applied/clawback ≤ 0), the spendable credit, the NEWEST 12 months that carry entries, and one page of referred businesses with their figures." type ReferralReport { "Every business that signed up with your code — gone ones included." referredCount: Int! pendingCount: Int! approvedCount: Int! deniedCount: Int! "Referred businesses that no longer exist on the platform (their rows read blank — no code, no standing)." goneCount: Int! "Referred businesses with at least one earning entry (accrue or usage)." earningCount: Int! "Lifetime Σ accrue + usage (USD cents, ≥ 0)." earnedUsdCents: Int! "Lifetime Σ applied — your own base fees credit-settled from earnings (USD cents, ≤ 0)." appliedUsdCents: Int! "Lifetime Σ clawback — dispute reversals (USD cents, ≤ 0)." clawbackUsdCents: Int! "Your wallet's spendable referral credit (USD cents). Null when the group holds no wallet." spendableUsdCents: Int "The NEWEST 12 months that carry entries, NEWEST-first." months: [ReferralMonth!]! "One page of your referred businesses, NEWEST-first by the referred group's id (limit clamps [1,200] default 50; before = a strict id upper bound — the affiliateAccruals grammar)." referrals: [ReferralPerformance!]! } "The caller group's handholding-plan report (the quarterly HUMAN-support plans, consumption-sized): the LIVE size classing (what a purchase today charges), the ruled per-incident price, and the plan's standing in the ONE coverage vocabulary." type SupportPlanReport { "The size class the trailing quarter's consumption lands in TODAY (small | medium | large | enterprise — the bands, half-open: ≥10,000 tok/mo enterprise · ≥2,000 large · ≥400 medium · under 400 small)." sizeClass: String! "What a quarter at that class charges, USD cents ($500 · $1,000 · $2,000 · $7,500 — the v3.5 ladder, the public page's own figures)." quarterUsdCents: Int! "The classing basis in whole tokens/month (display words — the exact compare runs in kernels)." basisTokensPerMonth: Int! "The size-threshold config version that classed it." thresholdsVersion: Int! "The planless per-incident HUMAN-support price, USD cents ($50 — 'the paid tow', a deliberate-ask deductible; it stays open during the activation wait)." incidentUsdCents: Int! "The coverage standing: none | pending_first_collection | waiting (inside the 72 h activation wait) | active | active_canceled (paid coverage serves; renewals stopped) | lapsed." standing: String! "the instant the wallet's complimentary onboarding window ENDS (the wallet's birth + 90 days — the first 90 days include handholding-equivalent human support at the base price). Absent = the group holds no wallet." onboardingUntil: String "is the onboarding window covering RIGHT NOW (server-computed — no activation wait applies; the window is not purchasable)?" onboardingCovers: Boolean! "The latest purchase instant (absent = never purchased)." purchasedAt: String "purchasedAt + the 72 h activation wait in force at purchase (the CAA law — a plan serves no incident before this)." activatesAt: String "The last COVERED month, UTC YYYY-MM (absent while the first collection is un-settled)." coveredThroughMonth: String "The cancel instant (absent = standing)." canceledAt: String } "Custody attach input." input AttachTokenAccountBillingMethodInput { "The Stripe PaymentMethod token (pm_…) to store for off-session charging." methodRef: String! } "The block-transfer ask." input RequestKernelBlockTransferInput { "The blocks to move (each == its purchase id; distinct; ≤ 16)." blockIds: [ID!]! "The receiving org group." toOrgGroupId: ID! "Why — the review reads it." reason: String! } "No further notes." input GrantTokensInput { "The receiving org group (the wallet's root)." orgGroupId: ID! "The POSITIVE grant magnitude (a grant loads tokens)." amountTokens: Int! "REQUIRED — root money moves always say why." reason: String! } "No further notes." input AdjustTokensInput { orgGroupId: ID! "The SIGNED non-zero correction." amountTokens: Int! "REQUIRED — corrections always say why." reason: String! } "No further notes." input TransferTokensInput { "The sending org group (its wallet posts the negative side)." fromOrgGroupId: ID! "The receiving org group (its wallet posts the positive side)." toOrgGroupId: ID! "The POSITIVE magnitude moved (the pair is sum-conserving by construction)." amountTokens: Int! "REQUIRED — the operator-approval trail." reason: String! } "No further notes." type TokenGrantResult { entry: TokenEntry! tokenAccount: TokenAccount! } "No further notes." type TokenTransferResult { outEntry: TokenEntry! inEntry: TokenEntry! fromTokenAccount: TokenAccount! toTokenAccount: TokenAccount! } "The review queues hold NON-terminal requests only (rows release at the terminals); history reads by id forever." type ChangeRequest { id: ID! "No further notes." type: String! "The CQ-… sysId." sysId: String! caption: String! "submitted | in_review | needs_info | approved | realizing | realized | realization_failed | rejected | cancelled." status: String! "The registry — 'onboarding_signup' (the public signup) | 'org_park' | 'org_unpark'." requestType: String! "The ONBOARDING profile's form (present ⟺ requestType is onboarding_signup — the profile pair is exactly-one-set; the ONE resubmit-mutable field)." payload: OnboardingSignupPayload "The MANAGEMENT profile's form." lifecyclePayload: OrganizationLifecyclePayload "The reviewer's clarification ask (stamped by requestChangeRequestInfo; the v1 answer lane is out-of-band + resubmitChangeRequest)." needsInfoNote: String "The rejection reason." rejectReason: String "The convergent-resume stamps." realizedAccountId: ID realizedOrgGroupId: ID "Present ⟺ the realization's classification minted the fused wallet." realizedTokenAccountId: ID "No further notes." realizedClassification: String "The last realization fault, (stamped by system:realization_error; superseded by a successful retry)." realizationFault: String createdAt: String! updatedAt: String! revisionNum: Int! } "The prospect's evaluation scope — DERIVED from the contracts ONBOARDING_EVALUATION_SCOPES." enum OnboardingEvaluationScope { one_location one_workflow whole_business } "The launch countries — DERIVED from the contracts LAUNCH_COUNTRIES. The signup payload’s country rides it; every org-create jurisdiction is gated to the same roster." enum LaunchCountry { CA US AU NZ } "The prospective merchant's signup form." type OnboardingSignupPayload { email: String! loginName: String! accountCaption: String groupCaption: String! message: String "The optional referral code." referralCode: String "The prospect's evaluation scope." evaluationScope: OnboardingEvaluationScope "The merchant’s country." country: LaunchCountry } "The submit/resubmit form (the payload's input twin)." input OnboardingSignupPayloadInput { "The owner Account's email — the one-live-signup-per-email UNIQ coordinate (frees at every terminal)." email: String! "The desired owner loginName — ADVISORY until realization reserves it." loginName: String! accountCaption: String "The merchant's business/group display caption." groupCaption: String! "Free-text context for the reviewer — bounded; never machine-consumed." message: String "The optional referral code." referralCode: String "The Terms-of-Service acceptance: the CURRENT published version string, accepted verbatim. SDL-optional for wire compatibility, but the submit engine REQUIRES it equal to the current version — absent/stale refuses the ONE opaque signup sentence." tosVersion: String "The OPTIONAL evaluation scope: what the prospect wants to prove first — one_location | one_workflow | whole_business; a stray value is refused by the enum itself; resubmit may change it (a stated intent, not a reservation coordinate)." evaluationScope: OnboardingEvaluationScope "The merchant’s country: one of the launch countries. SDL-optional for wire compatibility, but the submit engine REQUIRES it — absent refuses naming the field; a non-launch value is refused by the enum itself; resubmit may change it (a stated fact, not a reservation coordinate)." country: LaunchCountry } "No further notes." type SubmitOnboardingSignupResult { requestId: ID! status: String! "The human-readable application reference (the CQ-… sysId — slice; the support/registration handle)." reference: String! } "What the PUBLIC redeem returns." type RedeemOnboardingEmailVerificationResult { status: String! } "What the PUBLIC resend ask returns." type ResendOnboardingEmailVerificationResult { status: String! } "What the PUBLIC reset ask returns." type RequestPasswordResetResult { status: String! } "What the PUBLIC reset completion returns." type CompletePasswordResetResult { status: String! } "What the PUBLIC reset-context read returns: the account email behind a LIVE reset token — the set-new-password page’s account line + the username field a password manager pairs with the new password." type PasswordResetContext { email: String! } "The PUBLIC resend ask." input ResendOnboardingEmailVerificationInput { "The application reference from the receipt — CQ-XXXX-XXXX-XXXX (any casing)." reference: String! "The application's email, exactly as submitted." email: String! } "The MANAGEMENT profile's form." type OrganizationLifecyclePayload { organizationId: ID! "Free-text context for the reviewer (why park/unpark) — bounded; never machine-consumed." message: String } "The submit/resubmit form of the MANAGEMENT profile (the payload's input twin — ruling)." input OrganizationLifecyclePayloadInput { "The target Organization — ⚠ the pending-(type×org) reservation coordinate: resubmit may NOT change it (the onboarding email law's exact analog; a different org is a NEW request)." organizationId: ID! "Free-text context for the reviewer — bounded; never machine-consumed." message: String } "No further notes." type ChangeRequestPage { items: [ChangeRequest!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the walk is complete." nextToken: String } "No further notes." type ReferralCode { id: ID! "The RD-… sysId." sysId: String! caption: String! "active | inactive (disabled — the marker KEPT, new signups refuse) | doomed (declared-dormant)." status: String! "single_email (bound, once, may carry the promotion) | multi (open attribution; optional caps/window) — immutable at birth." kind: String! "The NORMALIZED code (trim + UPPERCASE — entry is case-insensitive; immutable at birth, the coupon law)." code: String! "The attribution label the born group's referredBy carries (e.g. partner-podcast)." channel: String! "The AFFILIATE org group commissions accrue to — absent = house/campaign attribution." ownerOrgGroupId: ID "single_email ONLY: the ONE prospect email this code serves (matched case-insensitively at submit)." boundEmail: String "single_email ONLY: the v1 percent×cycles base-fee promotion the born group is stamped with." billingPromotion: ReferralBillingPromotion "multi ONLY: the total-consumption cap." maxUses: Int "multi ONLY: the half-open [startAt, endAt) window start (absent = already open)." startAt: String "multi ONLY: the half-open window end (absent = evergreen)." endAt: String createdAt: String! updatedAt: String! revisionNum: Int! } "The v1 referral billing promotion." type ReferralBillingPromotion { "platform_fee_discount (the future-variant seam)." kind: String! percent: Int! cycles: Int! } "The promotion's input twin (kind explicit — strict; only platform_fee_discount exists v1)." input ReferralBillingPromotionInput { kind: String! percent: Int! cycles: Int! } "No further notes." input NewReferralCodeInput { "Optional display caption — defaults to the normalized code." caption: String "The RAW vanity code (normalized trim+UPPERCASE server-side) — ABSENT ⇒ the kit GENERATES REF-XXXX-XXXX." code: String "single_email | multi." kind: String! channel: String! ownerOrgGroupId: ID boundEmail: String billingPromotion: ReferralBillingPromotionInput maxUses: Int startAt: String endAt: String } "The usage story." type ReferralCodeUsage { "Live reservations + consumptions (multi — bounded by maxUses modulo the disclosed check-then-add race)." held: Int! "Realized births — the attribution stat." used: Int! "single_email: a live application holds (or a realized one consumed) the pending slot." singleReserved: Boolean! } "The root read result — the code + its usage story." type ReferralCodeDetail { referralCode: ReferralCode! usage: ReferralCodeUsage! } "One ReferralCode page — the PERMANENT REFERRALREG walk: every code, ANY status (≠ the live-only onboarding queue)." type ReferralCodePage { items: [ReferralCode!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the walk is complete." nextToken: String } "One generic note on ANY same-tenant construct. Internal-only in v1 (no consumer face — CsCase owns that lane)." type Note { id: ID! type: String! caption: String! "active (a posted fact) — the void lane is FSM data with NO wire op (the CaseMessage class)." status: String! "The annotated TARGET construct (ANY same-tenant type — the note's parent)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! revision: ID! "The target's construct type — SERVER-STAMPED from the existence read (the tombstone render's anchor)." targetType: String! "The authoring staff User (server-stamped from the principal — notes are internal-only in v1)." authorId: ID! "No further notes." parentNoteId: ID "The optional lead line (1..120; immutable — the ledger law)." title: String "The kind ∈ {comment, question, action} (unnamed births stamp 'comment'; pre- rows answer the default — states ride later)." kind: String! "The note body (1..4096)." body: String! "The outbound links (≤8; absolute http(s):// only — the scheme fence held at the boundary)." links: [NoteLink!] "No further notes." attachments: [NoteAttachmentMeta!] "The bound construct references (≤8, distinct by (type,id) — validated in-tenant + non-doomed at write; ref-ONLY per the @375 law: a purged target renders as a tombstone)." refs: [TaskConstructRef!] "The mentions (≤8, distinct by target; each landed ONE inbox message in the birth txn — the MSG lane)." mentions: [NoteMention!] "The labels (≤8 — the SHARED TaskLabel vocabulary; ACTIVE at write)." labelIds: [ID!] "SET-ONCE, server-stamped; the face joins the state chip through it against the tasksByConstruct page." taskId: ID "the referenced-caption rule: the server-composed captions for refs + mentions + labelIds under the caller-root gate — the surfaces speak names, never ids." refCaptions: [RefCaption!]! "The reaction groups." reactions: [NoteReactionGroup!] } "One reaction group." type NoteReactionGroup { emoji: String! count: Int! userIds: [ID!]! } "One mention on a note." type NoteMention { userId: ID teamId: ID } "One outbound link on a note." type NoteLink { url: String! "Optional display label; absent ⇒ the surface renders the URL." label: String } "sha256 = the mint-declared digest the presigned PUT itself enforced (byte custody)." type NoteAttachmentMeta { "The attachment id (the BLOBBOOK SK; minted at upload-mint)." id: ID! filename: String! "The declared MIME — registry-validated against the filename's extension at mint." declaredContentType: String! "The blob's byte size (declared at mint; HeadObject-verified at attach-confirm)." bytes: Int! sha256: String! "No further notes." key: String! } "ONE door's count on a record's Explore level — the referencing family (its construct type name), the reference field on that family, and the EXACT count of that family's live records whose field names the record (the family's OWN filtered listing's matchCount — the very number the door shows when opened); null when the family did not fit the call's hydration budget (never a guess — the face renders the glyph alone)." type RelationshipDoor { family: String! field: String! count: Int } "The relationshipCounts answer: every door the caller may open (a family whose listing the caller's roles refuse is OMITTED, never 0) with its count; partial = at least one door answered null (the hydration budget ran out on that family)." type RelationshipCounts { doors: [RelationshipDoor!]! partial: Boolean! } "One page of a construct's note thread." type NotePage { items: [Note!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the thread is complete. Opaque + target-bound." nextToken: String } "Link input." input NoteLinkInput { url: String! label: String } "Append-input for addNote." input NewNoteInput { "The annotated construct (ANY same-tenant type — existence + same-rootId gate; a cross-tenant/missing target refuses NOT_FOUND)." targetConstructId: ID! "The target's declared construct type (the ruling — constructs key by (type,id), so the existence read NEEDS the type and PROVES the declaration; a mismatch refuses NOT_FOUND opaquely; the TaskConstructRef law)." targetType: String! "The note body (1..4096)." body: String! "No further notes." parentNoteId: ID "The optional lead line (1..120)." title: String "The kind ∈ {comment, question, action} — unnamed stamps 'comment' (the Task-priority idiom; server-validated)." kind: String "Outbound links (≤8 — the scheme fence)." links: [NoteLinkInput!] "The caller's own PRIOR upload-mints to bind (≤8, distinct; each un-bound + on the SAME target — the attachment-first flow)." attachmentIds: [ID!] "The construct refs (≤8, distinct by (type,id); in-tenant + non-doomed at write — the TaskConstructRef law)." refs: [TaskConstructRefInput!] "The mentions (≤8, distinct by target; userId ⊕ teamId each — the sendMessage recipient gates verbatim [a USER in-tenant + non-doomed, suspended still receives; a TEAM must be ACTIVE with the CALLER a member]; each lands ONE inbox message in the birth txn)." mentions: [NoteMentionInput!] "The labels (≤8, distinct — ACTIVE TaskLabels; the ONE shared vocabulary)." labelIds: [ID!] } "One mention input." input NoteMentionInput { userId: ID teamId: ID } "Upload-mint input." input MintNoteAttachmentUploadInput { targetConstructId: ID! "The target's declared construct type (the NewNoteInput.targetType law — verified by the existence read)." targetType: String! "The original filename (≤255; no path separators + no NUL — the boundary fence; the DERIVABLE blob key carries no filename [the ruling]; downloads serve it via response-content-disposition)." filename: String! declaredContentType: String! bytes: Int! "No further notes." sha256: String! } "No further notes." type NoteAttachmentUploadHeader { name: String! value: String! } "The upload ticket: a short-TTL presigned PUT against the write-once blob key, PRE-TAGGED pending (the 7-day lifecycle reaps never-attached orphans). Bind the attachmentId via addNote before the TTL's practical window closes." type NoteAttachmentUploadTicket { "The minted attachment id — pass to addNote.attachmentIds to bind." attachmentId: ID! "The full blob key the ticket writes (notes[-scanned]//…)." key: String! "The presigned PUT URL (short-TTL)." uploadUrl: String! "The headers the PUT must carry VERBATIM (signed conditions — checksum + tagging)." requiredHeaders: [NoteAttachmentUploadHeader!]! "When the ticket expires (ISO-8601)." expiresAt: String! } "Download-mint input." input MintNoteAttachmentDownloadInput { noteId: ID! attachmentId: ID! } "The download ticket: a short-TTL presigned GET (the verdict gate already passed for scanned-prefix blobs)." type NoteAttachmentDownloadTicket { attachmentId: ID! filename: String! declaredContentType: String! bytes: Int! "The presigned GET URL (short-TTL)." downloadUrl: String! "When the ticket expires (ISO-8601)." expiresAt: String! } "Upload-mint input." input MintWizardMaterialUploadInput { "The wizard's kind word (the fill lanes' `type` — e.g. Item, Brand; the material composes ONLY into this wizard's presses)." wizardType: String! "The original filename (≤255; no path separators + no NUL — the boundary fence; the derivable blob key carries no filename)." filename: String! declaredContentType: String! bytes: Int! "No further notes." sha256: String! } "The material upload ticket (the NoteAttachmentUploadTicket law): PUT to uploadUrl sending EVERY requiredHeader verbatim, then confirmWizardMaterial(id) before the pending lifecycle's window closes." type WizardMaterialUploadTicket { "The minted material id — pass to confirmWizardMaterial to review + keep it." materialId: ID! "The full blob key the ticket writes (materials//…)." key: String! "The presigned PUT URL (short-TTL)." uploadUrl: String! "The headers the PUT must carry VERBATIM (signed conditions — checksum + tagging)." requiredHeaders: [NoteAttachmentUploadHeader!]! "When the ticket expires (ISO-8601)." expiresAt: String! } "One confirmed wizard material: what later fill/guide presses compose from." type WizardMaterial { id: ID! "The wizard word the material binds to (the walk-scope fence — it composes only into this wizard's presses, only for its uploader)." wizardType: String! filename: String! declaredContentType: String! bytes: Int! "THE EXTRACTION — the AI's bounded fact-sheet distillation of the material (≤1600 chars; the material's only memory)." extraction: String! createdAt: String! } "The takeSuggestion input." input TakeSuggestionInput { id: ID! revision: ID! reason: String } "One skill's detector fault from a desk refresh." type SuggestionSkillFault { skill: String! "The refusal's major/minor code (e.g. VALIDATION/INVALID)." code: String! message: String! } "The desk refresh outcome: minted = fresh offers born · superseded = stale offers closed for changed content · expired = past-due opens flipped · skippedDuplicate = identical open twins (the evidence-set dedup law) · skippedDeclined = the learning signal held · skippedTaken = the living-walk hold · skippedCapped = the per-skill/per-day/open bounds · schemasEnsured/doomedHeld = the v2 registrations minted / held permanently killed · parkedSkills = detectors the org has parked (they never ran)." type RefreshSuggestionsResult { minted: Int! superseded: Int! expired: Int! skippedDuplicate: Int! skippedDeclined: Int! skippedTaken: Int! skippedCapped: Int! schemasEnsured: Int! doomedHeld: Int! parkedSkills: Int! skillFaults: [SuggestionSkillFault!]! } "The askConsultation input — the target + its current revision, your question, and optionally YOUR OWN confirmed materials (≤4, minted with wizardType 'consultation' — their STORED extractions compose, raw files are never re-read)." input AskConsultationInput { id: ID! revision: ID! message: String! materialIds: [ID!] } "One transcript page (the caseMessages page shape — oldest first; nextToken walks forward)." type ConsultationTurnPage { items: [ConsultationTurn!]! nextToken: String } "One surface's call count inside a usage day." type AiUsageSurfaceCalls { "The metered surface token — e.g. office.assistant, office.form_fill (the at.ai.call.v1 vocabulary)." surface: String! calls: Int! "The surface's OUTPUT tokens that day." tokensOutput: Int! } "One UTC day of YOUR group's AI usage." type AiUsageDay { "The UTC day (YYYY-MM-DD)." day: String! calls: Int! tokensInput: Int! tokensOutput: Int! "The day's platform-key spend — a DECIMAL STRING in USD (nano-dollar exact; the money-string law — never a float)." costUsd: String! "The per-surface split where the day carries it (days that predate the split answer honestly — totals stay whole)." surfaces: [AiUsageSurfaceCalls!]! } "YOUR group's AI-usage window: the days WITH usage, newest first, + the window totals." type AiUsageWindow { days: [AiUsageDay!]! totalCalls: Int! totalTokensInput: Int! totalTokensOutput: Int! "The window's total spend — a DECIMAL STRING in USD (the money-string law)." totalCostUsd: String! } "One fired AI-watch flag: WHO tripped WHICH pattern on WHAT day, with the window's count at the crossing. The watch CATCHES and never blocks — this row exists so a human decides." type AiFlagEntry { "The UTC day the flag fired in." day: String! "The tripped pattern — daily_volume | same_request_hour | same_request_day | burst_5min | throttle_bump (the AI_WATCH_PATTERNS registry; thresholds are GENEROUS v1, tightened on merchant data)." pattern: String! "READ-side actor resolution: 'user' when actorId resolves to an in-tenant User, else 'other' (a session-keyed actor, or a user since removed) — worded honestly, never guessed." actorKind: String! "The watched actor — a user id (office surfaces) or the session id the event carried (the consumer/api/device planes)." actorId: ID! "The actor's caption when actorKind is 'user' (resolved at read — never stored on the flag)." actorCaption: String "How many times the pattern TRIPPED that day (hour/burst windows can cross again in fresh windows — each crossing grows this row and speaks its own loud line; the inbox task mints on the day's FIRST fire only)." count: Int! } "YOUR group's fired AI-watch flags: newest day first." type AiFlagWindow { flags: [AiFlagEntry!]! } "One door a ledger row points at (🧾 — REFS never blobs): the kind is one of type · record · material · consultation · session · course; the id its coordinate (a type word, a sysId or id, a material id, a consultation id, a session id, a course key)." type AiCallRef { kind: String! id: String! } "The token counts of one AI call (the at.ai.call.v1 shape): cachedInput and cacheWrite ride INSIDE input; reasoning rides INSIDE output." type AiCallTokens { input: Int! cachedInput: Int! cacheWrite: Int! output: Int! reasoning: Int! } "One AI provider call YOUR group made, WITH the words (🧾 THE AI LEDGER): the merchant's prompt · the office-composed context · what the model said it understood · the answer · the refs — beside the metering facts the daily rollup already shows. The words live here and in the event lake ONLY; no log line ever carries them." type AiCall { "= the meter event's callId (the provider call's own uuidV7) — the same id the response envelope's extensions.at.ai.calls.id carries." id: ID! at: String! "The wire request's own id (= that response's extensions.at.callId) — every AI call of one press carries it (a planner's route + steps + resolve; a consultation's rounds)." requestId: ID! "The wire operation the call served — draftReport · askConsultation · interpretFilter · …" op: String! "The metered surface token (the at.ai.call.v1 roster) — e.g. office.report_draft." surface: String! provider: String! "The EXACT model id the provider reported." model: String! "The reasoning effort the call rode — low | medium | high | xhigh (low everywhere in slice 1)." effort: String! schemaName: String! "ok | refused | error | timeout." status: String! providerErrorCode: String tokens: AiCallTokens! "The call's cost — a DECIMAL STRING in USD (nano-dollar exact; the money-string law — never a float)." costUsd: String! priceTableVersion: String! latencyMs: Int! bytesIn: Int bytesOut: Int "The MERCHANT's words; null where the surface has none (a summary roll, a material extraction, a training draft)." prompt: String "The office-composed context the merchant handed the surface (the page's identity form · the filled fields · the thread); null where none; cut at 8192 with contextTruncated true." context: String contextTruncated: Boolean! "What the model said it understood the request to be (the echo rule — one sentence, at most 240 characters); null when the call did not answer." understood: String "The surface's answer as it parsed it (the strict JSON text after the echo strip); null when the call did not answer; cut at 16000 with answerTruncated true." answer: String answerTruncated: Boolean! refs: [AiCallRef!]! userId: ID sessionId: ID organizationId: ID } "One page of YOUR group's AI calls, NEWEST first (the OrgBusEntryPage grammar)." type AiCallPage { items: [AiCall!]! "Present ⇒ more may remain (pass back verbatim as nextToken; a surface-filtered walk may return a SHORT page with one — keep walking); null ⇒ the walk reached the 13-month floor (or the ONE month asked is exhausted)." nextToken: String } "The wizard draft's state — DERIVED from the contracts FILL_DRAFT_STATES (the enum weld rule): drafting (the assistant is working in the background) · ready (the sheet landed — review it) · failed (it could not be made; failReason says why) · taken · abandoned (closed by you)." enum FillDraftStatus { drafting ready failed taken abandoned } "One page the caller SENT for the draft — the step word and its WANT lines (one per empty field: name — label (kind): help), the fill press's own grammar." type FillDraftPageSpec { step: String! want: String! } input FillDraftPageInput { "The page's step word (1..120) — unique across the pages; the sheet answers by it." step: String! "The page's empty fields, one per line as name — label (kind): help (1..2000 characters)." want: String! } "One drafted value in the sheet: the EXACT field name from WANT, the text to type (≤ 400), where it came from (the material’s name, or 'your text'), and how sure the assistant was." type FillDraftField { name: String! value: String! source: String! "high | medium | low." confidence: String! } "One page of the drafted sheet — the SENT step word + its drafted fields (deduped by name; at most 40); a page the assistant had nothing for is absent." type FillDraftSheetPage { step: String! fields: [FillDraftField!]! } "One background wizard draft (🤖 — slice): YOUR text and/or documents in, a drafted sheet across EVERY page of the walk out — in the background (the assistant thinks at its highest effort; the machine polls every 8 s inside a 480 s wall). The sheet (pages · questions · advice · understood) is ABSENT until status ready; failReason is present on failed. DRAFTS ONLY — nothing is created or applied; you review every value. expiresAt = the draft's lifetime in epoch seconds (startedAt + 30 days)." type FillDraft { id: ID! sysId: String! type: String! caption: String! status: FillDraftStatus! "The drafting person (the draft is theirs alone)." parentId: ID! rootId: ID! revision: ID! revisionNum: Int! createdAt: String! updatedAt: String! "The wizard word the draft was asked for (Item · Location · …) — prompt context and the materials' walk-scope word." wizardType: String! "Your text ('' on a documents-only draft)." brief: String! materialIds: [ID!]! "The pages you sent, in walk order." pages: [FillDraftPageSpec!]! "What was already answered when you asked ('' on a fresh wizard)." filled: String! sheet: [FillDraftSheetPage!] "At most 5 — where the materials disagree, or a required field has no support." questions: [String!] advice: String "What the assistant said it understood (the echo rule) — present once the draft is ready." understood: String turnCount: Int! "what the assistant remembers of the conversation so far — the stored rolling summary; absent until the older turns fold (past 12 un-summarized turns)." summary: String "turns before this ordinal live inside the summary; from it on, they are composed verbatim. 0 until the first fold." summarizedThroughSeq: Int! "the message the assistant is answering right now — present only while a talk is in flight (status drafting)." activeTurnId: ID activeTurnStartedAt: String failReason: String sfExecutionArn: String startRequestId: ID! startedAt: String! readyAt: String "when the sheet was taken into the record the wizard created — present iff status taken (set once)." takenAt: String "the record the draft was taken into — its sysId (or its id) as the taker named it at the take; present only on a taken draft whose take named one (a plain take carries none). A reference, never resolved." takenRef: String expiresAt: Int! } "Who spoke a turn — DERIVED from the contracts FILL_DRAFT_TURN_ROLES (the enum weld rule): user (you) · assistant." enum FillDraftTurnRole { user assistant } "How an assistant turn went — DERIVED from FILL_DRAFT_TURN_OUTCOMES: ok (the reply and the revised sheet landed) · failed (told; failReason says why; the sheet unchanged)." enum FillDraftTurnOutcome { ok failed } "One turn of a draft's conversation (🤖 — slice): seq is the conversation ordinal (0-based); createdAt the transcript timestamp. YOUR turns carry your message (body), your materials and the request they rode; the ASSISTANT's carry the reply, outcome, failReason iff failed, sheetRevised (the sheet changed under this reply) and what it said it understood." type FillDraftTurn { id: ID! seq: Int! role: FillDraftTurnRole! body: String! materialIds: [ID!] requestId: ID outcome: FillDraftTurnOutcome failReason: String sheetRevised: Boolean understood: String createdAt: String! } "One page of a draft's conversation, OLDEST first (the transcript order; nextToken walks forward)." type FillDraftTurnPage { items: [FillDraftTurn!]! nextToken: String } "The talkFillDraft input: the draft + its current revision, your message (say, 1..8192), and optionally up to 4 of YOUR OWN confirmed materials on the SAME wizard word (their stored fact sheets compose)." input TalkFillDraftInput { id: ID! revision: ID! say: String! materialIds: [ID!] } "The talkFillDraft answer — the draft (now drafting; activeTurnId names your turn) + your turn as appended. The assistant's turn lands in the background — poll the draft or read fillDraftTurns when it is ready again." type TalkFillDraftResult { draft: FillDraft! turn: FillDraftTurn! } "One page of YOUR wizard drafts, NEWEST first (the house page grammar). A page may be SHORT — the owner and status filters ride per id page; walk until nextToken is null." type FillDraftPage { items: [FillDraft!]! nextToken: String } "What to draft from and over: the wizard word · the pages (every page's WANT at once; ≤ 12) · what is already FILLED · your text (brief, ≤ 8192) and/or up to 4 of YOUR OWN confirmed wizard materials on the SAME wizard word (their stored fact sheets compose — never a raw re-read). At least one of brief / materialIds." input StartFillDraftInput { "The wizard's kind word (1..64) — the fill press's type; the materials' walk-scope word." wizardType: String! "Optional; the default is ' draft — '." caption: String brief: String materialIds: [ID!] pages: [FillDraftPageInput!]! "The whole walk's answered label: value lines (0..4000); absent = nothing yet." filled: String } "One dimension's kernel figure inside a usage-report day." type UsageReportDimensionKernels { "The metered dimension token — e.g. compute, api_call, ai_usage (the rate card's vocabulary)." dimension: String! "Integer KERNELS (the public unit — 1 kernel is one millionth of an internal token)." kernels: Float! } "One UTC day of YOUR group's metered consumption at the asked lane." type UsageReportDay { "The UTC day (YYYY-MM-DD)." day: String! "Rated events contributing to this row." calls: Int! "Integer KERNELS consumed (the µtoken IS the kernel)." kernels: Float! "The per-dimension split (only dimensions with usage appear)." dimensions: [UsageReportDimensionKernels!]! } "YOUR group's consumption window at ONE lane: the days WITH usage, newest first, + the window totals." type UsageReportWindow { days: [UsageReportDay!]! totalCalls: Int! "The window's total KERNELS." totalKernels: Float! "The window's per-dimension totals (only dimensions with usage appear)." totalDimensions: [UsageReportDimensionKernels!]! } "One session — a sitting: the WHO rides parentId (a User for user sittings; an ApiKey for api; a Consumer for consumer; a Device for device; a Collaborator for collaborator; an AgentChannel for agent_platform), the WHEN rides createdAt/updatedAt. Deadlines, accounts, and credentials stay OFF the wire BY DESIGN." type Session { id: ID! "The session class: user | api | consumer | device | collaborator | agent_platform." kind: String! "active, expired, revoked, or doomed — terminals persist." status: String! "The principal the sitting belongs to — a User (user kind), ApiKey (api), Consumer (consumer), Device (device), Collaborator (collaborator), or AgentChannel (agent_platform); join it to the staff roster for the display name." parentId: ID! "The organization the session acts in." orgId: ID! "The sign-in instant (ISO)." createdAt: String! "The last write instant (ISO) — activity rolls the idle deadline forward, so this approximates last-seen." updatedAt: String! } "One NEWEST-FIRST page of the sessions listing." type SessionPage { "The page's records, newest first (doomed drops per page — a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Session!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "A bookmark subject family — USER = the personal set · TEAM = the team's shared working set." enum BookmarkSubjectKind { USER TEAM } "The feed/list scope (the office v3 Profile tabs): ALL = mine + my teams (deduped) · OWN = my personal set · TEAM = my teams' sets." enum FeedScope { ALL OWN TEAM } "One subject whose bookmark surfaced a feed card (the All-tab merge attribution)." type BookmarkVia { subjectKind: BookmarkSubjectKind! ownerId: ID! } "One raw bookmark row." type BookmarkRef { subjectKind: BookmarkSubjectKind! "The subject — the calling user's own id (USER) or a team id (TEAM)." ownerId: ID! targetType: String! targetId: ID! createdAt: String! "WHO performed the bookmark act (for TEAM rows: the member who added it — provenance)." createdBy: ID! boostedAt: String popAt: String "The private-curation stamp (USER rows only by op construction — the Highlights tab filters on it)." highlightedAt: String } "One composed feed card." type FeedCard { targetType: String! targetId: ID! "The target's human id (addressable constructs carry one; never invented)." sysId: String caption: String! status: String! "The target's own last-write instant." updatedAt: String! "The feed sort key — max(target activity, my boost, a DUE scheduled pop); newest first." effectiveAt: String! "The EARLIEST bookmark instant across the surfacing subjects." bookmarkedAt: String! "Every subject whose bookmark surfaced this card (deduped target — the All-tab merge)." via: [BookmarkVia!]! "The calling user's OWN row's boomerang stamps (team stamps contribute to effectiveAt only)." boostedAt: String popAt: String "The calling user's OWN highlight stamp." highlightedAt: String "The target's last conversation instant." activityAt: String "The NOTE card's anchor — the annotated construct's declared type; null on every non-note card." anchorType: String "The NOTE card's anchor id (the anchorType twin — the thread route's id)." anchorId: ID } "The inbox a message is addressed to." enum MessageSubjectKind { USER TEAM } "Who sent it." enum MessageFromKind { USER SYSTEM } "One inbox message." type MessageRef { id: ID! "The inbox — YOUR user id (USER) or a team id (TEAM)." toKind: MessageSubjectKind! toId: ID! fromKind: MessageFromKind! "The sender (USER) or the attributed actor (SYSTEM — null for a pure platform notice)." fromUserId: ID body: String! "The optional 'about this record' ref — both present or both null." targetType: String targetId: ID createdAt: String! "USER rows: null = unread; TEAM rows: always null (no per-member read state v1)." readAt: String } "One page of the merged inbox walk." type MessageRefPage { items: [MessageRef!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the walk reached the tenant's birth month. Opaque + user-bound." nextToken: String } "The notice vocabulary — DERIVED from the contracts NOTIFICATION_KINDS." enum NotificationKind { burn_breach low_balance fraud_alert billing_charge_failed support_plan_renewed support_plan_lapsing owner_verification_pending referral_approved referral_denied search_finished search_expired search_failed export_finished export_expired export_failed training_certificate_issued training_required training_refresh_due release fill_draft_finished } "The notice attention class — DERIVED from the contracts NOTIFICATION_SEVERITIES: blocking (urgent) · needs_decision (a person must act) · informational (good to know)." enum NotificationSeverity { blocking needs_decision informational } "One platform notice to YOUR account. Month-bucketed at the occasion's own instant; the occasion facts are immutable; readAt stamps first-read-wins." type NotificationRef { "The deterministic occasion id — ## (pass verbatim to markNotificationRead)." id: ID! kind: NotificationKind! "The attention class: DERIVED from the kind through the contracts NOTIFICATION_SEVERITY map at read time, never stored — the attention box, the badge and the mail words derive from it." severity: NotificationSeverity! "WHEN it happened — burn_breach: the UTC day; low_balance: the episode-start instant; fraud_alert: the raise instant; the search kinds: the job's finish instant; the export kinds: the export job's finish instant; release: the wave's flip instant." occasionAt: String! "WHICH kernel wallet (the /costs door target) — the alarm kinds' subject; null on fraud_alert." tokenAccountId: ID "WHICH fraud alert (the /fraud-alerts door target) — the fraud_alert subject; null on the alarm kinds." fraudAlertId: ID "WHICH background search (the /search-jobs//matches door target) — the search_finished · search_expired · search_failed subject; null on the other kinds." searchJobId: ID "WHICH background export (📤 — the /profile door today; ’s export room re-points it to /exports/) — the export_finished · export_expired · export_failed subject; null on the other kinds." exportJobId: ID "WHICH training certificate (🎓 — the training_certificate_issued subject; the office notice's door is the Learn view /playbook?learn=1 — the design note; 🎓 — ALSO the training_refresh_due subject: the certificate whose course changed) — null on the other kinds." trainingCertificateId: ID "WHICH training requirement (🎓 — the training_required subject, the eighth exclusive axis: the rule that binds you and stands unmet; the door is the Learn view /playbook?learn=1) — null on the other kinds." trainingRequirementId: ID "WHICH wave (🆕 — THE CHANGES TAB slice 2 THE FEED; the design note) — the release subject, the NINTH exclusive axis: the wave tag the office words the notice from through its bundled changes table (the wave’s first title; “and N more”); the door is What’s new (/?tab=CHANGES) — null on the other kinds." changeTag: String "WHICH wizard draft (🤖 — THE FILL CONVERSATION slice; the design note) — the fill_draft_finished subject, the TENTH exclusive axis: the draft that became READY (read it with fillDraft; the office door is the landing '/' until opens the wizard on it); null on the other kinds." fillDraftId: ID createdAt: String! "null = unread." readAt: String } "One page of the notice walk." type NotificationRefPage { items: [NotificationRef!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the walk reached your account's birth month. Opaque + account-bound." nextToken: String } "One shipped change, in the merchant's words (🆕 — THE CHANGES TAB): what changed and why it matters, the surfaces it touched, the role templates it names, and the office door when one exists. Off the platform's bundled release table — nothing stored, nothing tenant-specific; every signed-in person reads the same rows (the office's What's new tab shows them)." type Change { "The row's key — - (e.g. -1); a page cursor names the last key it returned." key: String! "The wave that shipped it (e.g.)." tag: String! "The UTC day it shipped — YYYY-MM-DD." date: String! "What changed — at most 90 characters, plain words." title: String! "Why it matters — at most 300 characters, the merchant's voice." summary: String! "The surfaces touched — engine · cli · office · pos · www · assistants · plugins." surfaces: [String!]! "The role templates the change names (the people a release notice tells); empty = named to no one in particular — the tab shows every row to everyone." templates: [String!]! "An office path to open when the change has a door; null otherwise." doorPath: String "The door's words (“open What's new”); null without a door." doorWords: String "A link to the record of the change when one is given; null otherwise." record: String } "One page of the release record, NEWEST first (the house page grammar over a bounded table)." type ChangePage { items: [Change!]! "Present ⇒ more rows remain (pass back verbatim as nextToken); null ⇒ the list is exhausted. Opaque." nextToken: String } "The mail kinds — DERIVED from the contracts MAIL_KINDS." enum MailKind { verification verification_resend reviewed password_reset burn_breach low_balance support_plan_lapsing billing_charge_failed support_plan_renewed owner_verification_pending referral_approved referral_denied } "Where a mail came from — DERIVED from the contracts MAIL_ORIGINS: the requesting surface (a client app word, or undeclared) for the identity kinds; the firing lane for the others." enum MailOrigin { office pos partner cli mcp ucp goldens www undeclared usage_check balance_check billing_run owner_check processor_report referral_review } "One email the platform sent to YOUR account. The words derive at read time from the kind + origin." type MailLedgerEntry { "The footer reference — M-XXXX-XXXX-XXXX (pass verbatim to mailByRef)." ref: ID! kind: MailKind! "The kind in words (the letter's heading)." kindWords: String! origin: MailOrigin! "The origin in words — where the request came from, or which lane fired it." originWords: String! "The footer's own first line — the (kind × origin) sentence the mail carried." footerSentence: String! "The dedup marker's subject — the onboarding request · your Account · the wallet · the charge · the referred group." subjectId: ID! "The firing change event's id — the trace into the event lake." eventId: String! "When the firing event happened (the reference encodes it)." eventAt: String! "When the transport accepted the mail." sentAt: String! "The mail provider's own send id." providerMessageId: String! "SHA-256 hex of the recipient address, lowercased — compare, never read." recipientHash: String! } "One page of your mail-ledger walk (newest-first across your account's month buckets; walk until nextToken is null)." type MailLedgerPage { items: [MailLedgerEntry!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the walk reached your account's birth month. Opaque + account-bound." nextToken: String } "One tenant event card. Rows live ~90 days (the window); the per-record History keeps all of time." type OrgBusEntryRef { "The deterministic change id — # (newest-first is the wire order)." id: ID! "WHAT moved — the construct's type + id (the card's open door)." constructType: String! constructId: ID! "The record's sysId at the event." constructSysId: String "The record's caption at the event (as-of truth — a later rename does not rewrite history)." caption: String "The record's FSM state at the event." status: String "What kind of write: create · edit · transition." causeKind: String! "The transition's event name (transitions only — creates/edits have no declared vocabulary)." causeEvent: String "The acting lane's trigger token (doom · rename · a system lane's token) when the cause carried one." causeOp: String "The caller-supplied reason, verbatim, when one rode the write." causeReason: String "WHO — null on pre-provenance/engine writes (word those System)." actor: RevisionActorFace "The record's revision ordinal at the change (0 = its birth)." constructRevisionNum: Int! "WHEN — the record's own updatedAt at the change." occurredAt: String! } "One page of the tenant event walk." type OrgBusEntryPage { items: [OrgBusEntryRef!]! "Present ⇒ more may remain (pass back verbatim as nextToken; a filtered walk may return a SHORT page with one — keep walking); null ⇒ the walk reached the window's edge. Opaque + group-bound." nextToken: String } "One layout node — the identity trio + the live FSM status." type OrgLayoutNode { id: ID! sysId: String! caption: String! status: String! } "A logical facility with its registers (the till positions), sysId-ordered." type OrgLayoutLogicalFacility { id: ID! sysId: String! caption: String! status: String! registers: [OrgLayoutNode!]! } "A physical facility: its referenced site (null when the location row is gone) + its logical facilities, sysId-ordered." type OrgLayoutPhysicalFacility { id: ID! sysId: String! caption: String! status: String! location: OrgLayoutNode logicalFacilities: [OrgLayoutLogicalFacility!]! } "The acting organization's identity at the layout's head." type OrgLayoutOrganization { id: ID! sysId: String! caption: String! status: String! code: String! } "The acting org's operational tree in one read: Organization → PhysicalFacilities → LogicalFacilities → Registers. truncated = the antifragile node bound trimmed the deepest levels (real merchants never reach it)." type OrgLayout { organization: OrgLayoutOrganization! physicalFacilities: [OrgLayoutPhysicalFacility!]! truncated: Boolean! } "One batch child code's face — the code + its single-use story. Codes are distribution artifacts (listable), not secrets." type CouponBatchCodeFace { id: ID! "The generated code (-) — present a child code exactly like a parent code (applyOrderCoupon resolves both)." code: String! "unredeemed · redeemed (single-use spent — attach refuses) · clawed_back (a cancelled order reversed the use — redeemable again)." status: String! "Stamped at PLACE with the redeeming order; absent while unredeemed." redeemedAt: String orderId: ID } "The createCouponBatch result — the batch + its minted codes (also listable later via couponBatchCodes)." type CouponBatchMint { couponBatch: CouponBatch! codes: [CouponBatchCodeFace!]! } "One page of a batch's child codes (mint order; walk until nextToken is null)." type CouponBatchCodePage { items: [CouponBatchCodeFace!]! nextToken: String } "One membership row's face — the shopper + when they joined." type SegmentMemberFace { id: ID! consumerId: ID! createdAt: String! } "One page of a segment's members (consumerId order; walk until nextToken is null)." type SegmentMemberPage { items: [SegmentMemberFace!]! nextToken: String } "The addSegmentMembers result — the honest arithmetic (already-present shoppers SKIP, never error)." type AddSegmentMembersResult { added: Int! skippedExisting: Int! "The live meter after this call." memberCount: Int! } "The removeSegmentMembers result — deletes are idempotent (absent shoppers SKIP)." type RemoveSegmentMembersResult { removed: Int! skippedAbsent: Int! memberCount: Int! } "The refreshSegment result — sync (queued: false): the re-stamped segment + the honest arithmetic; queued (queued: true): the CURRENT segment, the arithmetic honestly ABSENT (the worker re-materializes shortly — evaluatedAt moves on completion; refreshProblem words a refresh that could not complete)." type RefreshSegmentResult { segment: Segment! "true = the universe exceeds the synchronous bound (10,000) — the refresh was QUEUED (the async lane); false = it ran in-request." queued: Boolean! "How many active consumers the predicate matched (after exclusions) — absent when queued." matched: Int added: Int removed: Int } "WHO performed one revision's write: kind names the actor class; exactly that class's ids ride beside it. Null on pre-provenance revisions — history is never fabricated." type RevisionActorFace { "user · consumer · collaborator · api · device · agent_platform · root · system · public (the unauthenticated public-ops lane)." kind: String! "The acting User (kind=user)." userId: ID "The acting User's Account (kind=user)." accountId: ID "The acting Consumer (kind=consumer)." consumerId: ID "The acting ApiKey construct (kind=api — the key, never its minter)." apiKeyId: ID "The acting Device (kind=device)." deviceId: ID "The acting AgentChannel (kind=agent_platform — the UCP door's principal, the platform's profile URL rides the Session row, never the stamp)." agentChannelId: ID "The AWS Access Key ID a root action ran under (kind=root, when the environment carried it — the root marker)." accessKeyId: String } "WHY one revision exists: the machine cause, with the caller's reason VERBATIM when the operation carried one, and — since locked — WHO as the typed actor face." type RevisionCauseFace { "create (birth) · edit (an attribute revision) · transition (an FSM state change)." kind: String! "The success-form event name of the matched transition (transitions only)." event: String "The transition trigger token (e.g. doom, activate); absent on creates/edits." op: String "The caller-supplied reason, VERBATIM; never required, never blank." reason: String "WHO wrote this revision; null on pre-provenance revisions." actor: RevisionActorFace } "One archived construct revision." type ConstructRevision { "The revision id (UUIDv7 — the OCC token this revision rotated to)." revision: ID! "The monotonic revision ordinal (0 = birth). A jump means the intervening revisions predate the archive — history is never fabricated." revisionNum: Int! "INSERT (birth) or MODIFY, as the stream recorded it." eventName: String! "The stream's approximate write instant (provenance — the record's own updatedAt inside recordJson is the revision timestamp); null on pre-provenance objects." archivedAt: String "The cause; null on pre-cause-era objects." cause: RevisionCauseFace "The full construct item at this revision, JSON-encoded (storage attributes stripped; money amounts are decimal strings VERBATIM)." recordJson: String! } "One resolved reference caption for a revision page: a referenced construct id that appears in this page's revisions, with its caption and type. Composed under the caller's root gate; unreadable/dangling references are simply absent." type RevisionCaption { id: ID! caption: String! type: String! } "One page of a construct's revision history." type ConstructRevisionPage { items: [ConstructRevision!]! "the merchant words for the referenced ids THIS page's revisions carry — old (re-pointed) values included; resolve client-side by id." captions: [RevisionCaption!]! "Present ⇒ more revisions remain (pass back verbatim); null ⇒ the trail is complete. Opaque + construct-bound." nextToken: String } "One suggested next action: a LIVE wire operation the CALLER may actually perform on the target, ranked by the curated per-type×state order. Render VERBATIM — the server already filtered and ranked (no client filtering by construction)." type SuggestedAction { "The operation's plain wire name (the op-list law) — e.g. deactivateBrand, closeTillSession." op: String! "One merchant-readable sentence: what taking this action does." why: String! } "Render VERBATIM — the server already ranked (overdue first; no client filtering by construction)." type NeedsAttentionEntry { "The registered source kind — 'task' (v1's one live source; the roster grows additively)." kind: String! "The target's construct type (the open-link rides the office directory — never a fake link)." targetType: String! targetId: ID! "The target's caption." caption: String! "One merchant-readable sentence — an overdue entry NAMES its due instant." reason: String! "The ranking instant (dueAt when present, else createdAt); null never fabricated." at: String } "One postal code's resolved tax jurisdictions: the usual designation first, the postal's other reachable jurisdictions after." type TaxJurisdictionPostalResolution { "The jurisdiction that usually applies at this postal code (the licensed table's primary designation). Null when the code is unknown here — or its designated node has been retired." primary: TaxJurisdiction "The postal code's OTHER jurisdictions — a code straddling city or district lines lists every candidate (bounded; most codes have none)." alternates: [TaxJurisdiction!]! } "The calling principal's OWN Account — the sign-in identity subset." type MyAccount { id: ID! sysId: String! caption: String! "The login identifier." loginName: String! email: String! status: String! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — informational here (no myAccount mutation exists); rotates on every account write." revision: ID! } "The calling principal's OWN organization group. The identity + governance facts ONLY — the referral provenance and the standings are NOT projected." type OrganizationGroup { id: ID! "The global human-facing system id (OG-…)." sysId: String! type: String! caption: String! "No further notes." status: String! "The globally-unique merchant code — a terse handle." code: String! "The classification — immutable at birth; governs the whole subtree." classification: String! "The owner Account ids; at least one." owners: [ID!]! "Null = none recorded." convertedFrom: String "The Terms of Service version accepted at signup, when stamped. Null on groups born before the ToS existed." tosAcceptedVersion: String createdAt: String! updatedAt: String! revisionNum: Int! } "The calling account's owner identity-verification standing." type IdentityVerificationReport { "True ⟺ the calling account holds ≥1 OWNER seat (the structural owners arrays on its reachable org groups/organizations — locked) — the requirement applies to it. Verification standing is meaningful regardless (once per account, forever)." required: Boolean! "The standing — requires_input | processing | verified | canceled (Stripe's own session vocabulary; requires_input WITHOUT error words = awaiting you, WITH them = a failed check awaiting retry). Null: verification was never started." status: String "The current Stripe VerificationSession reference (vs_…) — a pointer, never identity data (Stripe custodies the documents; this platform stores STATUS ONLY)." sessionRef: String "The first start's instant (UTC ISO)." requestedAt: String "The last truth stamp's instant (UTC ISO) — webhook results land within seconds; a stale non-terminal standing re-reads Stripe on this very query (self-healing)." updatedAt: String "Present exactly when verified — the once-per-account-forever fact's instant." verifiedAt: String "Stripe's last_error.code verbatim (e.g. document_expired) — present only after a failed check, always with its reason." lastErrorCode: String "Stripe's last_error.reason verbatim — the honest failure sentence the faces speak." lastErrorReason: String "True exactly when verified AND the verification is past the reported-staleness horizon (2 years: identity documents expire on their own cycles the platform cannot see, so the verification's own age is the honest proxy). INFORMATIONAL ONLY: verified is once per account FOREVER — nothing re-asks, nothing gates." aged: Boolean! } "One started (or re-opened) verification attempt: the hosted-flow door + the standing it opened against." type IdentityVerificationStart { "The standing after the start (a re-entry may discover verified/processing — the url is absent then)." status: String! "The Stripe VerificationSession reference (vs_…)." sessionRef: String! "The Stripe-hosted verification flow's url — SHORT-LIVED and single-use (open it now); absent when the session no longer accepts input (processing/verified). Re-invoking mints a fresh one." url: String } "One of the calling user's own app-private values." type MyAppDataEntry { app: String! name: String! "The opaque app-serialized payload (≤ 8 KB UTF-8)." value: String! createdAt: String! updatedAt: String! "Restamps on every put — last-write-wins per name is the accepted preference-data law." revision: ID! revisionNum: Int! } "One name's existence + stamps WITHOUT its value." type MyAppDataEntrySynopsis { app: String! name: String! createdAt: String! updatedAt: String! revision: ID! revisionNum: Int! } "The enrollDevice / reissueDevicePairingCode result — the device + its single-use pairing code, returned ONCE (hash-only at rest; the damm32 check symbol screens typos at entry)." type DeviceEnrollment { device: Device! "The single-use pairing code (XXXX-XXXX-XXXX, Crockford base-32 + check symbol) — shown ONCE, never readable again." pairingCode: String! "The code's expiry instant (15 minutes from issue — G 'short-lived')." pairingCodeExpiresAt: String! } "The completePairingDevice result — the now-active device + its credential, returned ONCE (hash-only at rest; exchanged for device sessions at the auth seam; mandatory 12-month rotation)." type DevicePairingResult { device: Device! "The device credential — shown ONCE; hold it in platform secure custody (iOS Keychain / Android Keystore; the BFF server-side for the browser POS — never in a browser)." deviceCredential: String! "The credential's rotation deadline." credentialExpiresAt: String! } "The revokeAllDeviceSessions result." type RevokeAllDeviceSessionsResult { device: Device! "How many live device sessions the kill switch revoked." revokedSessions: Int! } "The mintApiKey result — the key + its secret, returned ONCE (hash-only at rest; presented only to exchangeApiKey)." type ApiKeyMint { apiKey: ApiKey! "The key secret — shown ONCE, never readable again; never logged." secret: String! } "The exchangeApiKey result — the opaque API-session bearer token (returned ONCE) + its absolute deadline." type ApiKeyExchangeResult { token: String! "The session's absolute expiry instant (24 h from exchange)." expiresAt: String! "The exchanged key (reach + expiry visible; the secret never echoes)." apiKey: ApiKey! } "Create-input for enrollDevice." input EnrollDeviceInput { "Optional display caption; omitted ⇒ 'device at '." caption: String "The parent LogicalFacility — tenant-scoped + ACTIVE. Immutable after birth (re-home = doom + re-enroll)." logicalFacilityId: ID! deviceType: DeviceType! "Optional Register this device will serve once paired (POS classes only — a pi_bridge refuses one at the boundary; tenant-scoped + ACTIVE)." registerId: ID code: String } "Input for completePairingDevice." input CompletePairingDeviceInput { "The single-use pairing code from enrollDevice/reissueDevicePairingCode (XXXX-XXXX-XXXX; typo-screened by the check symbol before any lookup)." pairingCode: String! } "Input for reissueDevicePairingCode." input ReissueDevicePairingCodeInput { deviceId: ID! "The device revision the caller read." expectedRevision: ID! } "Input for pairDeviceToRegister." input PairDeviceToRegisterInput { deviceId: ID! "The Register to serve — tenant-scoped + ACTIVE." registerId: ID! "The device revision the caller read." expectedRevision: ID! } "Input for unpairDevice (the pairDeviceToRegister twin — clears the binding; the same live-TillSession refusal)." input UnpairDeviceInput { deviceId: ID! "The device revision the caller read." expectedRevision: ID! } "Input for revokeAllDeviceSessions." input RevokeAllDeviceSessionsInput { deviceId: ID! "Why the kill switch fired ('tablet reported stolen') — required, evented." reason: String! } "Create-input for mintApiKey." input MintApiKeyInput { "Optional display caption; omitted ⇒ 'api key minted by '." caption: String "The allow/disallow descriptor set. IMMUTABLE after minting." descriptors: [RoleDescriptorInput!]! "The mandatory expiry instant — at most 12 months out." expiresAt: String! } "Input for exchangeApiKey." input ExchangeApiKeyInput { "The key secret from mintApiKey — never logged, never stored plain." secret: String! "The org this session will act in." orgId: ID! } "Input for exchangeDeviceCredential." input ExchangeDeviceCredentialInput { "The device credential from completePairingDevice — never logged, never stored plain." credential: String! } "The exchangeDeviceCredential result: the opaque device-session bearer token (returned ONCE) + its deadlines (idle 24 h / absolute 7 d — long-lived, the normalization)." type DeviceSessionExchangeResult { token: String! "The session's absolute expiry instant (7 d from exchange)." expiresAt: String! "The session's initial idle deadline (24 h; rolls forward on use)." idleExpiresAt: String! "The exchanged Device (the WHERE facts — pairing visible; the credential never echoes)." device: Device! } "The createTerminalConnectionToken result." type TerminalConnectionTokenResult { "The Terminal connection token secret (pst_…) — feed it to the Stripe Terminal SDK's fetchConnectionToken callback verbatim." secret: String! } "The createWebhookSubscription result — the subscription + its signing secret, returned ONCE (plaintext in the non-streamed credential store; verify every delivery with it)." type WebhookSubscriptionMint { webhookSubscription: WebhookSubscription! "The signing secret — shown ONCE, never readable again; never logged. Deliveries sign almondtill-signature: t=,v1=. under THIS secret>." secret: String! } "The rotateWebhookSubscriptionSecret result — the fresh secret, returned ONCE; the old secret is dead from this instant (no dual-validity window — update your receiver FIRST)." type WebhookSubscriptionSecretRotation { webhookSubscription: WebhookSubscription! "The NEW signing secret — shown ONCE." secret: String! } "The pingWebhookSubscription receipt — accepted at EMIT; the delivery itself is asynchronous at-least-once through the real lane (watch your endpoint + the failure counters)." type WebhookPingReceipt { "Always true on a normal return (a refusal throws instead) — the receipt that the ping event entered the delivery lane." accepted: Boolean! "The ping's payload id — your endpoint's dedupe key for this test delivery." pingId: ID! } "Create-input for createWebhookSubscription." input CreateWebhookSubscriptionInput { "Optional display caption; omitted ⇒ 'webhook to '." caption: String "The https delivery endpoint — the egress law: https only, no credentials, no explicit port, no IP-literal/localhost/private-suffix hosts; ≤512 chars." targetUrl: String! "The event-name filter (1..64, deduped) — every name must be in the DERIVED deliverable universe (transition success events + at...create.ok.v1 birth names; the integrator docs enumerate it)." eventTypes: [String!]! "Optional Plugin binding — this subscription joins that plugin's declared event feed; the plugin must be a live in-group registration; IMMUTABLE after birth (a re-bind = a new subscription)." pluginId: ID } "No further notes." type FeedRunRef { "The object key — pass VERBATIM to mintFeedRunDownload." key: String! bytes: Int! "The run instant (the key's own basename — time-ordered lexically)." runAt: String! } "The mintFeedRunDownload ticket: fetch the file with a plain GET before it expires; re-mint per pull (the ticket IS the custody — there are no stored feed credentials)." type FeedRunDownloadTicket { url: String! expiresAt: String! } "Create-input for createFeedSubscription." input CreateFeedSubscriptionInput { "Optional display caption; omitted ⇒ ' feed'." caption: String "THE PER-ORG WELD: the ONE org this feed exports — an in-group LIVE Organization." organizationId: ID! "WHAT exports — one canned construct type (OrgCustomer · Style · Product · OrgVendor · Order)." dataset: String! "daily · weekly · monthly." cadence: String! "jsonl (lossless, the default posture) · csv (the flat scalar fields)." format: String! } "One eligible acting organization for a connector consent: ACTIVE and owned by YOUR account, the exchangeApiKey org gate mirrored (the grant names ONE org and every downstream exchange re-runs that gate)." type ConnectorAuthorizationOrg { id: ID! sysId: String! caption: String! } "A VALIDATED connector authorize request, resolved for the consent face: the client's words + the redirect host PROMINENT (the consent MUST) + the RFC 8252 loopback flag + the scope story + YOUR eligible orgs. An invalid request REFUSES typed and the face shows the error — the wire never builds a redirect from an unvalidated request (the open-redirect law)." type ConnectorAuthorizationReview { "The presented client_id — a dcr_… registration or a CIMD https URL (the identity the grant will bind to)." clientId: String! "The client's self-declared display name (absent when the registration carried none — show the clientId)." clientName: String "Where the client's identity came from: dcr (a registered row) or cimd (a fetched client-metadata document)." clientSource: String! "The EXACT redirect the browser will be sent to on approve/deny (already matched against the client's registered URIs — loopback matches port-agnostic per RFC 8252)." redirectUri: String! "The redirect's host, for PROMINENT display (the spec's consent MUST: the user sees where the code goes)." redirectHost: String! "True when the redirect is an RFC 8252 loopback (a local program on the approver's machine will receive the code — the face carries the extra warning)." loopback: Boolean! "The scope the grant will carry (v1: almondtill:read — the read-only integration template; the minted key's descriptors are the law server-side)." scope: String! "True when the client asked for offline_access (a refresh token — the connector stays signed in without re-consent until revoked)." offlineAccess: Boolean! "The RFC 8707 resource the tokens will be bound to (the canonical MCP endpoint)." resource: String! "YOUR eligible acting orgs (ACTIVE + owned by your account), sysId-ordered — the consent names exactly ONE." eligibleOrgs: [ConnectorAuthorizationOrg!]! } "The consent verdict's redirect instruction: send the browser HERE — code+state+iss on approve, error=access_denied+state+iss on deny (RFC 9207: iss rides EVERY authorization response)." type ConnectorAuthorizationVerdict { redirectTo: String! } "One RESERVED booking overlapping the asked window." type AvailabilityBooking { appointmentId: ID! "The window start (UTC instant)." startAt: String! "The window end, exclusive (start + duration — UTC instant)." endAt: String! } "The availability answer — the SRCD's own words: availability = resource hours − booked appointments (DERIVED; the client composes free slots; zero server timezone math — hours are naive wall-clock ADVISORY)." type SchedulableResourceAvailability { resourceId: ID! "Concurrent-booking capacity — up to this many bookings may overlap." capacity: Int! "The resource's advisory weekly hours (naive wall-clock — no gate consumes them)." workingHours: [WorkingHoursWindow!]! "The RESERVED bookings overlapping [from, to) — confirmed/in_progress appointments only (requested ones hold no slot)." bookings: [AvailabilityBooking!]! } "Complete-input for completeAppointment." input CompleteAppointmentInput { appointmentId: ID! "The doc revision the caller read." expectedRevision: ID! "The billing order to LINK (in-tenant, non-doomed-class) — the last legal moment; omitted = no link." orderId: ID reason: String } "Reschedule-input for rescheduleAppointment." input RescheduleAppointmentInput { appointmentId: ID! "The PREDECESSOR's revision the caller read." expectedRevision: ID! "The successor's UTC start instant (the lead/advance create gates re-run)." startAt: String! durationMinutes: Int resourceIds: [ID!] reason: String } "Claim-input for fileClaimWarranty." input ClaimWarrantyInput { warrantyId: ID! "The warranty revision the caller read." expectedRevision: ID! "The customer-service case the claim is filed under — in-tenant, caseType warranty_claim, not closed/cancelled (CONFLICT/REF_STATE otherwise); stamped warrantyId in the same transaction." caseId: ID! reason: String } "The rescheduleAppointment result: the doomed predecessor + the requested-born successor, linked bilaterally." type AppointmentReschedule { "The superseded appointment (now rescheduled — slot released; successorAppointmentId stamped)." predecessor: Appointment! "The successor (born requested — ITS confirm runs the capacity gate; predecessorAppointmentId stamped)." successor: Appointment! } "One canned storefront theme. The key is the stable contract the DTC render packages ship against." type StorefrontTheme { "The stable theme key a Storefront's theme field names." key: String! caption: String! "One honest line on what the theme is for." description: String! } "One canned fiscal regime: merchants pick a key, never author regimes. model = signature (sign + gap-free number + journal; EU-typical) | clearance (the authority authorizes BEFORE issuing; LATAM/Québec-typical). US carries no row — no national regime exists." type FiscalRegime { "The stable regime key issueFiscalReceipt names." key: String! caption: String! "signature | clearance — the two ratified models." model: String! "ISO-3166 alpha-2 of the regime's country." countryCode: String! } "A FiscalReceipt: the gap-free sequential fiscal number + the regime's signature (model A) or clearance authorization code (model B) + the QR payload the printed receipt renders. IMMUTABLE once issued — no edit, no transitions, no doom (the ⚑none artifact class; status is the one literal 'issued' forever). Certified partners produce the artifact fields — the caller never supplies them." type FiscalReceipt { id: ID! "The group-scoped human-facing system id (FR-…)." sysId: String! type: String! caption: String! "Always 'issued' — the artifact class carries ONE state and no FSM." status: String! "The fiscalized document." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — immutable artifact: it never rotates after birth." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule, the face slice grew it, as the build promised) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "order | invoice — which book the parentId names." parentKind: String! "The canned regime key (cannedFiscalRegimes lists the roster)." regime: String! "The establishment the series journals — the parent Order's selling LF (an Invoice inherits its Order's)." logicalFacilityId: ID! "The series identity — always # (fiscal series are establishment-bound)." seriesKey: String! "The gap-free sequential fiscal number WITHIN the series (1-based — allocated in the issue transaction)." seq: Int! "Model A — the partner/device fiscal signature (opaque, partner-shaped); null on a clearance-model receipt." signature: String "Model B — the authority's clearance authorization code (obtained BEFORE issuing); null on a signature-model receipt." authorizationCode: String "What the printed receipt renders as QR/barcode." qrPayload: String! "The certified partner's own document reference (null when the partner supplies none)." partnerRef: String } "One page of the org group's fiscal receipts (newest-first; walk until nextToken is null)." type FiscalReceiptPage { items: [FiscalReceipt!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Issue-input for issueFiscalReceipt." input IssueFiscalReceiptInput { "order | invoice — which book parentId names." parentKind: String! "The fiscalized document: an in-tenant Order at completed, or an Invoice at issued/closed (voided refuses)." parentId: ID! "A canned regime key (cannedFiscalRegimes lists the roster; an unknown key refuses NAMING it)." regime: String! } "One per-currency amount in an answered money metric." type DashboardMetricAmount { currency: String! "The summed amount in the currency's minor units (signed)." amountMinor: Int! } "One widget's answered value: available:true carries kind (count | money | percent | rating) + the matching figure + asOf; available:false carries a plain-words reason (more rows than one honest glance can total, nothing to measure yet, or an organization the buy desk has not evaluated) and nothing else. A figure is never clipped, estimated, or silently partial." type DashboardMetricValue { available: Boolean! "count | money | percent | rating — present ONLY when available." kind: String "The counted figure (kind = count; low_stock_count sums the per-organization buy-desk snapshots, asOf = the OLDEST evaluation)." count: Int "The per-currency sums (kind = money; inventory_value excludes items without a cost basis — no cost, no value opinion)." amounts: [DashboardMetricAmount!] "BASIS POINTS, 0..10000 (kind = percent — 3452 = 34.52%; sell_through_30d = net units sold over the trailing 30 UTC days ÷ (net sold + on hand now), the velocity NET convention: a returned unit moves from sold to held)." percentBp: Int "The average ×100, 100..500 (kind = rating — 437 = 4.37 stars over the PUBLISHED review census)." ratingCenti: Int "The census behind the rating (kind = rating — an average without its sample size would lie)." sampleCount: Int "The instant the figure is true at (ISO-8601; compute-on-read for the live lanes; the substrate-fed lanes carry their fold/evaluation instant)." asOf: String "Present ONLY when unavailable — merchant words naming exactly why." reason: String } "One widget row answered — the dashboard's own layout, ordinal ascending." type DashboardWidgetMetric { metricKey: DashboardMetric! ordinal: Int! value: DashboardMetricValue! } "The dashboardMetrics answer — the layout's widgets, each realized at read time." type DashboardMetrics { dashboardId: ID! widgets: [DashboardWidgetMetric!]! } "One trailing net-demand window." type VelocityWindow { days: Int! "Net demand over the window (may be negative — returns exceeded sells)." netQty: String! } "The resolved parameter VALUES for one (variant × LF) — exactly the registry keys, most-specific setter each." type ResolvedReplenishmentParameters { replenishEnabled: Boolean minUnits: String maxUnits: String daysOfSupplyTarget: Int safetyStockUnits: String reorderMultipleUnits: String reviewCadenceDays: Int abcClassOverride: AbcClass buyVsTransfer: ReplenishmentBuyVsTransfer reserveFloorUnits: String transferableExcess: Boolean allocationWeight: Int } "Per-parameter provenance: WHICH config set the winning value + its specificity trace." type ReplenishmentParameterSource { parameter: String! configId: ID! configSysId: String "Count of SET axes (0–4) — the specificity primary." axisCount: Int! "Location level: 0 = all, 1 = org, 2 = LF." locationLevel: Int! "Merchandise level: none | category: | style (style outranks any depth)." merchandiseLevel: String! seasonLevel: Int! brandLevel: Int! } "The replenishmentParameters diagnostic result." type ReplenishmentParameterResolution { variantId: ID! logicalFacilityId: ID! organizationId: ID parameters: ResolvedReplenishmentParameters! sources: [ReplenishmentParameterSource!]! "Every ACTIVE config whose set axes matched this target (winners AND out-ranked matches)." matchedConfigIds: [ID!]! } "Per-line provenance — every suggested number traceable: the position parts, the levels, the velocity readings, the config refs, the vendor pick." type SuggestionLineProvenance { inventoryItemId: ID! availableQty: String! inTransitQty: String! onOrderQty: String! positionQty: String! reorderPointQty: String! targetLevelQty: String! rawDeficitQty: String! "The reorder multiple applied (the forced reorderMultipleUnits override?? the pack unitsPerPack); absent = none." roundingMultipleQty: String "The effective stock-unit MOQ (pack-denominated junctions compare moq × unitsPerPack — the machinery); absent = none." effectiveMoqQty: String velocity: [VelocityWindow!]! configIds: [ID!]! chosenOrgVendorItemId: ID "The out-ranked candidates, in pick order." alternativeOrgVendorItemIds: [ID!]! "flags: zero-velocity · velocity-not-consumed · unit-cost-inexact · cost-comparison-skipped-mixed-currencies · transfer-cost-exceeds-buy · pack-quantity-exceeds-max · backfill-of-donor." annotations: [String!]! } "One DRAFT-PO-SHAPED line (realization-ready VERBATIM for createPurchaseOrder — lean): pack entry when the rounded qty is whole packs, unit entry otherwise (ONE entry mode per line, the XOR law)." type SuggestedPurchaseOrderLine { variantId: ID! logicalFacilityId: ID! quantity: String packQuantity: Int purchasePackId: ID "The EXACT per-stock-unit cost when derivable (plain listCost, or the pack division when exact-at-4dp) — informational; the create op re-derives authoritatively." estimatedUnitCost: String provenance: SuggestionLineProvenance! } "One suggested purchase order — deficits grouped by OrgVendor; orderMinimum shortfalls are ANNOTATED, never padded (the operator decides)." type SuggestedPurchaseOrder { orgVendorId: ID! organizationId: ID! currency: String lines: [SuggestedPurchaseOrderLine!]! "Σ line qty × exact unit cost (exact arithmetic, up to 8 fraction digits); absent when any line cost is unknown." estimatedTotal: String orderMinimum: String orderMinimumShortfall: String "Order-level flags: order-minimum-shortfall · order-minimum-uncomputable." annotations: [String!]! } "One TR-SHAPED line (realization-ready for createTransferRequest — pull semantics; the TR doc IS the demand doc)." type SuggestedTransferRequestLine { variantId: ID! quantity: String! provenance: SuggestionLineProvenance! } "One suggested transfer request — a deficit filled from ONE donor in the lane order." type SuggestedTransferRequest { requestingLogicalFacilityId: ID! targetLogicalFacilityId: ID! lines: [SuggestedTransferRequestLine!]! "How the donor entered the ordering (the lane basis / rank / distance / no-geo flags)." lane: TransferLaneRankingSource annotations: [String!]! } "The -g buy-vs-transfer-and-backfill COUPLED pair: transfer-now (D ← donor) + a backfill PO refilling the DONOR — shared provenance; suggested ONLY when the deficit is URGENT (projected stockout inside the horizon — velocity-dependent; zero-velocity books default to the plain PO, disclosed)." type SuggestedCoupledPair { transferNow: SuggestedTransferRequest! backfillPurchaseOrder: SuggestedPurchaseOrder! "Projected days until stockout at the deficit LF (display grade)." urgencyDaysUntilStockout: Float annotations: [String!]! } "A non-suggestion: no-ovi · no-donor · no-weights · deficit-unfilled." type SuggestionGap { inventoryItemId: ID variantId: ID logicalFacilityId: ID annotation: String! detail: String } "The replenishmentSuggestions result." type ReplenishmentSuggestionsResult { purchaseOrders: [SuggestedPurchaseOrder!]! coupledPairs: [SuggestedCoupledPair!]! gaps: [SuggestionGap!]! } "The rebalanceSuggestions result — one TR-shaped payload per donor." type RebalanceSuggestionsResult { transferRequests: [SuggestedTransferRequest!]! gaps: [SuggestionGap!]! } "Allocation line provenance — the hub's excess derivation + the destination's resolved weight." type AllocationLineProvenance { availableQty: String! targetLevelQty: String! reserveFloorQty: String excessQty: String! allocationWeight: Int! annotations: [String!]! } "One Transfer-SHAPED line (realization-ready for createTransfer — push semantics; the line names the SOURCE InventoryItem, the.1 shape)." type SuggestedTransferLine { inventoryItemId: ID! variantId: ID! quantity: String! provenance: AllocationLineProvenance! } "One suggested push Transfer — the hub's genuine excess fair-shared by the destinations resolved allocationWeight (largest remainder; never-lanes drop their destination)." type SuggestedTransfer { sourceLogicalFacilityId: ID! destinationLogicalFacilityId: ID! lines: [SuggestedTransferLine!]! annotations: [String!]! } "The allocationSuggestions result." type AllocationSuggestionsResult { transfers: [SuggestedTransfer!]! gaps: [SuggestionGap!]! } "How one source entered the ordering into a destination: a stored lane mode (never / always / ranked) or the sparse geodistance DEFAULT." type TransferLaneRankingSource { sourceLfId: ID! "never | always | ranked | default." basis: String! rank: Int laneId: ID weightClass: TransferLaneWeightClass "Great-circle km off the LF→PF→PFL.geo chain; absent when either side has no geo seed." distanceKm: Float "Both endpoints resolve to ONE PhysicalFacilityLocation." samePfl: Boolean! "A geo-absent side — ranks LAST within its group, LOUDLY flagged (never silent)." noGeo: Boolean! } "One resolved matrix row into the destination: ordered position among CONSIDERED sources; never entries are SHOWN position-less (excluded from consideration)." type TransferLaneRankingEntry { destinationLfId: ID! sourceLfId: ID! basis: String! rank: Int laneId: ID weightClass: TransferLaneWeightClass distanceKm: Float samePfl: Boolean! noGeo: Boolean! position: Int } "One classified book: value × velocity with registry cut lines (A < 80% cumulative share, B < 95%, else C; zero-score books are C); abcClassOverride pins the class (overridden: true)." type AbcClassEntry { inventoryItemId: ID! variantId: ID! logicalFacilityId: ID! abcClass: AbcClass! "velocity-value (any velocity in scope) | value (zero-velocity scope orders by WMA × on-hand alone — -i, disclosed) | zero." scoreBasis: String! "This book's share of the total score, percent (2 dp display grade)." sharePercent: Float overridden: Boolean! } "One value on a matrix axis, in ordinal order — ties by caption then id (the productOptions law). A projection of the OptionValue record — rename/recode the OptionValue, never this face." type StyleMatrixAxisValue { optionValueId: ID! caption: String! code: String ordinal: Int! } "One matrix axis: a scheme dimension of the Style in SCHEME order — the OptionGroup, its tier, the RESOLVED size run for this dimension (the style's own pick when its group matches, else the group's default, else null), and its values. A projection of the OptionGroup record — rename the OptionGroup, never this face." type StyleMatrixAxis { optionGroupId: ID! caption: String! tier: SchemeTier! sizeRunId: ID values: [StyleMatrixAxisValue!]! } "One live Product of the Style: the header words + the declared segment. A projection of the Product record — rename/recode the Product, never this face." type StyleMatrixProduct { productId: ID! caption: String! code: String status: String! segment: [ProductSegmentEntry!]! } "One cell of the matrix — a live Variant at the asked LogicalFacility: the coordinate in SCHEME order (re-sorted from the caller-ordered store), the owning InventoryItem when the (variant × LF) junction exists (else null and every quantity 0), on hand · reserved as stored, available = on hand − reserved (the IV-d law, never stored), on order from the InventoryItem's onOrderQty (maintained by the purchase-order walks and the receipt post — THE WALK). Quantities are decimal strings. A projection of the Variant record — rename/recode the Variant, never this face." type StyleStockCell { variantId: ID! productId: ID! caption: String! code: String status: String! coordinate: [VariantCoordinateEntry!]! inventoryItemId: ID onHandQty: String! reservedQty: String! availableQty: String! onOrderQty: String! } "The matrix totals — Σ over every cell by exact decimal addition." type StockMatrixTotals { onHandQty: String! reservedQty: String! availableQty: String! onOrderQty: String! } "ONE Style's stock matrix at ONE LogicalFacility: the axes in scheme order, the live products, the cells sorted axis-major by ordinal, the totals, the cell count." type StyleStockMatrix { styleId: ID! logicalFacilityId: ID! axes: [StyleMatrixAxis!]! products: [StyleMatrixProduct!]! cells: [StyleStockCell!]! totals: StockMatrixTotals! cellCount: Int! } "One filled entry of a size run: the OptionValue, its share, and the whole units it receives." type SizeRunFillCell { optionValueId: ID! share: Int! quantity: Int! } "One drifted junction: the InventoryItem whose STORED onOrderQty differs from the DERIVED truth (the receivable purchase orders' open quantity for its variant × logical facility), both as decimal strings. A projection of the InventoryItem record — repair the junction, never this face." type InventoryOnOrderAuditRow { inventoryItemId: ID! variantId: ID! logicalFacilityId: ID! stored: String! derived: String! } "ONE page of the on-order audit: the drifted rows of this page of the tenant's junctions, the page's drift count, and the junction cursor (null on the last page)." type InventoryOnOrderAuditPage { items: [InventoryOnOrderAuditRow!]! driftCount: Int! nextToken: String } "The answer of ONE on-order repair: the junction as it now stands, the figure it held before, the derived figure it was stamped to, and whether anything changed (a converged cell answers false — nothing written)." type InventoryOnOrderRepair { inventoryItem: InventoryItem! previous: String! derived: String! changed: Boolean! } "A postal address — the structured street address a PhysicalFacilityLocation holds." type Address { line1: String! line2: String city: String! region: String postalCode: String "ISO 3166-1 alpha-2 country code." countryCode: String! } "Optional geocoordinates — SEED the TransferLane sourcing matrix; not a live routing driver." type Geo { lat: Float! lng: Float! } "A physical facility location — the SOLE holder of a street address (the PFL→PF→LF→Zone→Bin hierarchy); the first data-plane construct." type PhysicalFacilityLocation { id: ID! "The group-scoped human-facing system id (PL-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent org group; for a PFL parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! address: Address! geo: Geo "Optional mutable merchant reference code; uniqueness NOT enforced." code: String "The canonical TaxJurisdiction this address sits in. Absent = unclassified ⇒ origin tax resolution finds no jurisdiction (nexus-none zero tax, disclosed)." taxJurisdictionId: ID } "One page of the physicalFacilityLocations listing — the records + the opaque resume cursor." type PhysicalFacilityLocationPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PhysicalFacilityLocation!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Address input for creating a PhysicalFacilityLocation." input AddressInput { line1: String! line2: String city: String! region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! } "Geo input." input GeoInput { lat: Float! lng: Float! } "Create-input for a PhysicalFacilityLocation. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here." input NewPhysicalFacilityLocationInput { "Optional: when omitted the per-type default applies — the address line ('line1, city'); when supplied it must be non-blank." caption: String address: AddressInput! geo: GeoInput code: String "Optional origin classification — the canonical TaxJurisdiction of this address (shared-ref: must exist + be ACTIVE on the canonical tree; CONFLICT/REF_STATE otherwise)." taxJurisdictionId: ID } "Edit-input for a PhysicalFacilityLocation. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). Address edits are TYPO FIXES — a physical MOVE is a NEW PFL. A supplied taxJurisdictionId RE-POINTS the origin classification: shared-ref gated (exists + ACTIVE on the canonical tree — CONFLICT/REF_STATE otherwise; deliberately NOT tenant-scoped)." input EditPhysicalFacilityLocationInput { caption: String address: AddressInput geo: GeoInput code: String "Re-point the origin classification (shared-ref: exists + ACTIVE — CONFLICT/REF_STATE otherwise; supplied REPLACES, no clearing semantic yet)." taxJurisdictionId: ID } "A physical facility — an actual location of an Organization (parent = the org, NOT the family root); holds no address of its own — it references a PhysicalFacilityLocation (two or more orgs may share one PFL). NOT a policy level." type PhysicalFacility { id: ID! "The group-scoped human-facing system id (PF-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a PF parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The referenced PhysicalFacilityLocation — the PF's address." physicalFacilityLocationId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the physicalFacilities listing — the records + the opaque resume cursor." type PhysicalFacilityPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PhysicalFacility!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a PhysicalFacility. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) + physicalFacilityLocationId (the address ref) are tenant-scoped server-side and must both be active (STRICT)." input NewPhysicalFacilityInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Physical Facility'; when supplied it must be non-blank." caption: String "The parent Organization id." organizationId: ID! "The referenced PhysicalFacilityLocation id (the PF's address)." physicalFacilityLocationId: ID! code: String } "Edit-input for a PhysicalFacility. Every field optional, at least ONE required; supplied fields REPLACE. A supplied physicalFacilityLocationId RE-POINTS the PF's address: the new PFL is tenant-scoped server-side and must be active (STRICT / — CONFLICT/REF_STATE otherwise); the old PFL releases implicitly (the guard reads the pointer live — zero PFL writes)." input EditPhysicalFacilityInput { caption: String code: String "The NEW referenced PhysicalFacilityLocation (a re-point) — tenant-scoped server-side; must be active." physicalFacilityLocationId: ID } "A logical facility — where transactions actually occur (sales, purchasing, receiving, transfers); inventory is maintained at LF level. Parent = its PhysicalFacility (NOT the family root). A policy level." type LogicalFacility { id: ID! "The group-scoped human-facing system id (LF-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent PhysicalFacility; for an LF parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The DERIVED owning org: == the parent PF's parentId, stamped at birth by every create channel and immutable by construction (both spine hops are birth-immutable). Filterable on the roster (the org-scoped facilities ask — the chooser-scope axis). NON-NULL since — the backfill stamped the estate and the grandfather window closed." organizationId: ID! "The operating character: store/showroom | warehouse. Set at creation, IMMUTABLE thereafter; drives the future coordinate-standard policy default." classification: String! "The geographic-Division membership pointer. Setting it is the FIRST armed strict-selection gate: in-tenant + ACTIVE + geographic-type + an ACTIVE OrgDivision selection by the LF org, else CONFLICT/UNSELECTED. Absent = no geographic membership." geographicDivisionId: ID "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the logicalFacilities listing — the records + the opaque resume cursor." type LogicalFacilityPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [LogicalFacility!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a LogicalFacility. The tenant (org group) is derived SERVER-SIDE from the principal; physicalFacilityId (the parent PF) is tenant-scoped server-side and must be active (STRICT — a child may not be born under a non-active parent); a supplied geographicDivisionId is gated in-tenant + ACTIVE + geographic-type + selection-held (the gate)." input NewLogicalFacilityInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Logical Facility'; when supplied it must be non-blank." caption: String "The parent PhysicalFacility id." physicalFacilityId: ID! "The operating character: store/showroom | warehouse — immutable after birth." classification: String! "Optional geographic-Division membership — gated in-tenant + ACTIVE + geographic-type + an ACTIVE OrgDivision selection by the LF org (the gate, else CONFLICT/UNSELECTED)." geographicDivisionId: ID code: String } "Edit-input for a LogicalFacility. Every field optional, at least ONE required; supplied fields REPLACE. geographicDivisionId additionally accepts EXPLICIT null = leave the division (the CG-a clearing semantic; clears are never gated); a supplied NON-null value re-gates exactly like create. The classification is NOT editable (locked — set at creation); nor is the parent-PF ref (re-parenting is its own -guarded slice)." input EditLogicalFacilityInput { caption: String code: String "A NEW geographic-Division membership (gated: in-tenant + ACTIVE + geographic + selection-held — the gate), or EXPLICIT null to leave; omitted = unchanged." geographicDivisionId: ID } "A zone — a subdivision of a LogicalFacility (an LF has one or more; the granularity between the LF and its Bins). Parent = its LogicalFacility (NOT the family root). A policy level; the holdable-inventory characteristics are a LATER slice (they arrive with the Characteristic construct)." type Zone { id: ID! "The group-scoped human-facing system id (ZN-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent LogicalFacility; for a Zone parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional mutable locator within the parent LF — free-form until the coordinate-standard policy lands (its default derives from the LF classification)." coordinates: String "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the zones listing — the records + the opaque resume cursor." type ZonePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Zone!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Zone. The tenant (org group) is derived SERVER-SIDE from the principal; logicalFacilityId (the parent LF) is tenant-scoped server-side and must be active (STRICT — a child may not be born under a non-active parent)." input NewZoneInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Zone'; when supplied it must be non-blank." caption: String "The parent LogicalFacility id." logicalFacilityId: ID! coordinates: String code: String } "Edit-input for a Zone. Every field optional, at least ONE required; supplied fields REPLACE. The parent-LF ref is NOT editable (re-parenting is its own -guarded slice)." input EditZoneInput { caption: String coordinates: String code: String } "A bin — the LEAF of the facility hierarchy (a Zone has one or more): where stock physically sits (inventory records pointer-reference bins, a bin holding stock can never be doomed or deactivated until the stock is moved). Parent = its Zone (NOT the family root). NOT a policy level." type Bin { id: ID! "The group-scoped human-facing system id (BN-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Zone; for a Bin parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "REQUIRED mutable locator within the parent Zone — free-form until the coordinate-standard policy lands (the standard is policy-selected, inherited zone from LF from org)." coordinates: String! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the bins listing — the records + the opaque resume cursor." type BinPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Bin!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Bin. The tenant (org group) is derived SERVER-SIDE from the principal; zoneId (the parent Zone) is tenant-scoped server-side and must be active (STRICT — a child may not be born under a non-active parent)." input NewBinInput { "Optional: when omitted the per-type default applies — the merchant code when given, else the coordinates locator; when supplied it must be non-blank." caption: String "The parent Zone id." zoneId: ID! coordinates: String! code: String } "Edit-input for a Bin. Every field optional, at least ONE required; supplied fields REPLACE. The parent-Zone ref is NOT editable (re-parenting is its own -guarded slice)." input EditBinInput { caption: String coordinates: String code: String } "The 7 canned role-template keys." enum RoleTemplateKey { owner system_administrator manager associate_manager warehouse_associate sales_associate cashier } "One canned role template: usable via copyCannedRole → an ordinary editable group Role. Hard boundaries are explicit disallow rows; amounts NEVER appear." type CannedRole { key: RoleTemplateKey! caption: String! "The template version." version: Int! "The authority tier a copy confers." authorityTier: RoleTemplateKey! "The compiled descriptor list (the CAN/CANNOT matrix over the CURRENT universe; wildcard-encoded where the matrix has no soft-cannots, allow-listed otherwise)." descriptors: [RoleDescriptor!]! } "A descriptor polarity: allow grants; disallow ALWAYS wins over any allow (the only precedence)." enum RoleDescriptorPolarity { allow disallow } "One allow/disallow descriptor: service:action + polarity, per-segment * wildcards; segments drawn verbatim from the operation registry." type RoleDescriptor { "The logical service name (today: api), or *." service: String! "The service external operation name (a schema Query/Mutation field), or *." action: String! polarity: RoleDescriptorPolarity! } "A role — the group-scoped, merchant-authored authorization construct: 0..N allow/disallow descriptors over the service:action naming universe. Evaluation is flat: default-DENY, union the allow descriptors across the session-user acted-org ACTIVE roles, any matching disallow ALWAYS wins; per-segment * wildcards; no specificity ranking." type Role { id: ID! "The group-scoped human-facing system id (RL-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Role parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The allow/disallow descriptors: service:action + polarity, per-segment * wildcards, disallow-wins; non-* segments are drawn VERBATIM from the operation registry (STRICT at create/edit). May be empty (grants nothing — default-deny)." descriptors: [RoleDescriptor!]! "PROVENANCE: the canned template this Role was copied from (copyCannedRole); PORT-stamped, never caller-suppliable; absent on from-scratch roles. A copy NEVER auto-revs when the template does (fork semantics)." templateKey: RoleTemplateKey "PROVENANCE: the template version the copy compiled from; absent on from-scratch roles." templateVersion: Int "The authority tier this Role confers: stamped from the template at copy; editable via updateRole (role administration is — hard-disallowed to every non-admin template, so tier self-elevation is structurally out); absent ⇒ contributes NO tier (deny-by-default at the authority gate). A role carrying an effective allow api:* counts as owner tier regardless (the bootstrap-role rule)." authorityTier: RoleTemplateKey } "One page of the roles listing — the records + the opaque resume cursor." type RolePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Role!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Descriptor input — service:action + polarity; each segment * or a registry name (letter-start, alphanumeric/underscore, at most 64 characters; validated STRICT server-side against the operation registry)." input RoleDescriptorInput { service: String! action: String! polarity: RoleDescriptorPolarity! } "Create-input for a Role. The tenant (org group — the Role parent) is derived SERVER-SIDE from the principal — NEVER supplied here. descriptors is required but MAY be empty; at most 100 per role; exact duplicates refused; non-* segments must name the live operation registry (STRICT)." input NewRoleInput { "Optional: when omitted the per-type default applies — the constant 'Role'; when supplied it must be non-blank." caption: String "The allow/disallow descriptors; may be empty (grants nothing)." descriptors: [RoleDescriptorInput!]! "Optional authority tier; absent ⇒ the role confers no tier (deny-by-default at the authority gate)." authorityTier: RoleTemplateKey } "Edit-input for a Role. Every field optional, at least ONE required; supplied fields REPLACE. descriptors REPLACES WHOLESALE when supplied (the list is the payload; supplying strips every grant — default-deny). authorityTier replaces when supplied (no clearing semantic). templateKey/templateVersion are PORT-stamped provenance (copyCannedRole) — never editable. Assigning roles to users is NOT here — user-role assignment is its own slice." input EditRoleInput { caption: String descriptors: [RoleDescriptorInput!] authorityTier: RoleTemplateKey } "One org's role assignment for a User: the Organization id + the Role ids held there (min 1)." type UserOrgRoles { "The Organization the assignment applies at." org: ID! "The Role construct ids the user holds at that org (min 1; at most 100 — bounded)." roles: [ID!]! } "A user — an Account AT an Organization Group, holding Roles per organization within the group; the principal a login resolves. Fully realized since: createUser binds an EXISTING Account into the caller's group (at most ONE User per account × group — the userBinding reservation that IS the login index; a doomed holder's binding is taken over on re-add, SL-d), and the lifecycle transitions ride the OPERATIONAL template with the RULED session semantics — sessions never block and never cascade; a non-active User's sessions go INERT at the next resolve (the live-status extension)." type User { id: ID! "The group-scoped human-facing system id (US-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a User parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The Account this user binds — attribute, never key identity; NOT editable." accountId: ID! "No further notes." orgRoles: [UserOrgRoles!]! } "One page of the users listing — the records + the opaque resume cursor." type UserPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [User!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One org's role assignment — org + min-1 roles; every referenced org and role must be in-tenant AND active (validated STRICT server-side, CONFLICT/REF_STATE otherwise)." input UserOrgRolesInput { org: ID! roles: [ID!]! } "Create-input for a User. The tenant (org group — the User parent) is derived SERVER-SIDE from the principal — NEVER supplied here. accountId names the EXISTING Account to bind (miss → NOT_FOUND/CONSTRUCT; doomed → CONFLICT/REF_STATE; a restricted account is bindable). At most ONE User per (account × group): a live holder refuses CONFLICT/IDENTITY_TAKEN naming it; a DOOMED holder's binding is taken over atomically. orgRoles is required but MAY be empty; refs validated STRICT (in-tenant + active)." input NewUserInput { "Optional: when omitted the per-type default applies — the constant 'User'; when supplied it must be non-blank." caption: String "The EXISTING Account this user binds — immutable thereafter." accountId: ID! "The initial role-assignment set; may be empty (no org association yet)." orgRoles: [UserOrgRolesInput!]! } "Edit-input for a User. Every field optional, at least ONE required; supplied fields REPLACE. orgRoles REPLACES WHOLESALE when supplied (the list is the payload, supplying strips every assignment); at most 100 entries, one per org, each with 1..100 roles, duplicates refused; every referenced org + role must be in-tenant AND active (CONFLICT/REF_STATE). accountId is NOT editable (the binding is the user identity)." input EditUserInput { caption: String "The FULL desired assignment set (wholesale replacement — strips every assignment)." orgRoles: [UserOrgRolesInput!] } "A brand — an OPTIONAL product building block: who BRANDS the product, orthogonal to the Manufacturer (who built it) and the Vendor (who sold it); whatever the group wants — NOT the simple brand text property on the org group / org. The first catalog construct: a simple product references 0..1 brand (locked) at the spine; per-org enablement (OrgBrand) arrives; consumer-facing assets are Decorations." type Brand { id: ID! "The group-scoped human-facing system id (BR-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Brand parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String "Optional description; consumer-facing content is Decorations, a later slice." description: String } "One page of the brands listing — the records + the opaque resume cursor." type BrandPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Brand!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Brand. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here." input NewBrandInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Brand'; when supplied it must be non-blank." caption: String code: String description: String } "Edit-input for a Brand. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet); consumer-facing assets (logos, localized copy) are Decorations, a later slice — never fields here." input EditBrandInput { caption: String code: String description: String } "A season — a merchandising-calendar building block; an INSTANCE, not a recurring pattern. Master data ONLY: the merchandising lifecycle (planning → buying → selling → clearance) belongs to future process constructs that reference it — the optional selling window is reporting data, never an FSM trigger. Per-org enablement (OrgSeason) arrives; Product↔Season references at the spine." type Season { id: ID! "The group-scoped human-facing system id (SN-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Season parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional mutable merchant reference code, e.g.; uniqueness NOT enforced (the code stance)." code: String "Optional selling-window start (UTC ISO-8601) — reporting data, never an FSM trigger." startAt: String "Optional selling-window end (UTC ISO-8601); startAt ≤ endAt when both present." endAt: String } "One page of the seasons listing — the records + the opaque resume cursor." type SeasonPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Season!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Season. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; the optional selling window must satisfy startAt ≤ endAt." input NewSeasonInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Season'; when supplied it must be non-blank." caption: String code: String "Optional selling-window start (UTC ISO-8601)." startAt: String "Optional selling-window end (UTC ISO-8601); startAt ≤ endAt." endAt: String } "Edit-input for a Season. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). A one-sided window edit is validated against the STORED other side: startAt ≤ endAt must hold on the MERGED record (VALIDATION/INVALID otherwise)." input EditSeasonInput { caption: String code: String startAt: String endAt: String } "A tag — a group-defined label for catalog nodes: the cross-cutting, unstructured axis, distinct from categories (hierarchical navigation), options (variant-driving), and characteristics (validated values). STRICT: no free-string tags — a tag must exist as a construct before use (typo-proof; rename-safe via caption). Attachment = Tag reference sets on Styles and Products (variants excluded), arriving with the spine; TWO_STATE — no inactive (a label is usable or gone)." type Tag { id: ID! "The group-scoped human-facing system id (TG-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent org group; for a Tag parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the tags listing — the records + the opaque resume cursor." type TagPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Tag!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Tag. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here." input NewTagInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Tag'; when supplied it must be non-blank." caption: String code: String } "Edit-input for a Tag. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). A rename is safe by design." input EditTagInput { caption: String code: String } "A characteristic value type: string | number | date | pattern." enum CharacteristicValueType { string number date pattern } "The validation grammar (pattern, length) — the value-validation rules a characteristic imposes; pattern is an ECMAScript regex source (compile-checked server-side, <=256 chars)." type CharacteristicGrammar { pattern: String minLength: Int maxLength: Int } "A characteristic — a master-list entry for VALIDATED product values (serial-number, warranty period, …): value type + validation grammar + optional unit; distinct from Tags (unstructured labels), Categories (navigation), and Options (variant-driving). Canned + custom: system-shipped IMMUTABLE templates are copied via copyCannedCharacteristic; group-defined customs are created directly — references (the Manufacturer format map; the spine) always point at group-owned constructs, never templates. TWO_STATE — no inactive (a master-list entry is usable or gone)." type Characteristic { id: ID! "The group-scoped human-facing system id (CH-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent org group; for a Characteristic parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The value type (canned registry) — set at creation, IMMUTABLE thereafter." valueType: CharacteristicValueType! "Optional validation grammar; REQUIRED (with pattern) on a pattern-typed characteristic; refused on number/date (STRICT)." grammar: CharacteristicGrammar "Optional canned-UoM unit code; absent = dimensionless." unit: String "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the characteristics listing — the records + the opaque resume cursor." type CharacteristicPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Characteristic!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Grammar input — >=1 field when supplied; bounds ordered (minLength <= maxLength); pattern must compile (validated STRICT server-side against the stored valueType on edits)." input CharacteristicGrammarInput { pattern: String minLength: Int maxLength: Int } "Create-input for a Characteristic. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here. STRICT invariants: pattern-type requires a compiling grammar.pattern; number/date take NO grammar; unit only on number, naming a canned UoM." input NewCharacteristicInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Characteristic'; when supplied it must be non-blank." caption: String "The value type — immutable after birth." valueType: CharacteristicValueType! grammar: CharacteristicGrammarInput "A canned-UoM unit code (number-typed characteristics only)." unit: String code: String } "Edit-input for a Characteristic. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). valueType is NOT editable (immutable at birth, CH-c); a supplied grammar/unit is validated against the STORED valueType on the merged record (VALIDATION/INVALID otherwise — the merged-edit precedent)." input EditCharacteristicInput { caption: String code: String grammar: CharacteristicGrammarInput unit: String } "A UoM dimension class: count | mass | volume | length | area | time." enum UomDimensionClass { count mass volume length area time } "A custom unit of measure — a group-defined unit that MUST declare its dimension class + its conversion factor to the class BASE unit (STRICT: convertible by construction, e.g. Bolt = 25 m). The canned UoM registry (cannedUoms — the locked classes + maintained conversions) is registry DATA, not constructs; pack relationships (1 case = 12 each) are NOT UoM conversions. Referenced UoMs cannot be doomed (the guard arms with the Variant stock UoM)." type CustomUom { id: ID! "The group-scoped human-facing system id (UM-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a CustomUom parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The declared dimension class — set at creation, IMMUTABLE thereafter." dimensionClass: UomDimensionClass! "The conversion factor to the class BASE unit (count=each · mass=kg · volume=l · length=m · area=m2 · time=day); > 0, finite." factorToBase: Float! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the customUoms listing — the records + the opaque resume cursor." type CustomUomPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CustomUom!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a CustomUom. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; dimensionClass + factorToBase are REQUIRED (convertible by construction)." input NewCustomUomInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Custom UoM'; when supplied it must be non-blank." caption: String "The dimension class — immutable after birth." dimensionClass: UomDimensionClass! "The conversion factor to the class base unit; > 0, finite." factorToBase: Float! code: String } "Edit-input for a CustomUom. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). dimensionClass is NOT editable (immutable at birth, UM-a — changing the class breaks convertible-by-construction); factorToBase IS editable (a value, not an identity — its consuming slices add the reference gates)." input EditCustomUomInput { caption: String code: String factorToBase: Float } "One format rule — how THIS manufacturer formats characteristic X; the grammar vocabulary is the CharacteristicGrammar, reused verbatim." type ManufacturerFormatEntry { "The formatted Characteristic's id." characteristicId: ID! grammar: CharacteristicGrammar! } "A manufacturer — WHO BUILT the product: orthogonal to the Brand (who brands it) and the Vendor (who sold it to the merchant); the vendor-manufacturer linkage is never structural — it materializes per purchase. Carries the default ISO origin country and the characteristic FORMAT MAP (how THIS manufacturer formats serial numbers etc. — entries keyed by Characteristic id). Per-org enablement (OrgManufacturer selection, strictly required before any org reference) arrives." type Manufacturer { id: ID! "The group-scoped human-facing system id (MF-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Manufacturer parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional DEFAULT ISO 3166-1 alpha-2 origin country; finer granularity is Product-level (future)." origin: String "The characteristic format map (<=64 entries, unique per characteristic); absent = no format rules." characteristicFormats: [ManufacturerFormatEntry!] "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the manufacturers listing — the records + the opaque resume cursor." type ManufacturerPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Manufacturer!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Format-entry input — the target Characteristic must be in-tenant, active, and grammar-bearing (string/pattern valueType); validated STRICT server-side." input ManufacturerFormatEntryInput { characteristicId: ID! grammar: CharacteristicGrammarInput! } "Create-input for a Manufacturer. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here. Each format entry is gated server-side: in-tenant + ACTIVE Characteristic (doomed → CONFLICT/REF_STATE) whose valueType admits a grammar (string/pattern only — number/date → VALIDATION/INVALID, the rule)." input NewManufacturerInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Manufacturer'; when supplied it must be non-blank." caption: String code: String "ISO 3166-1 alpha-2 (uppercase)." origin: String characteristicFormats: [ManufacturerFormatEntryInput!] } "Edit-input for a Manufacturer. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). A supplied characteristicFormats list replaces WHOLESALE (the Role-descriptors precedent; releases every format rule) and is re-gated per entry exactly like create." input EditManufacturerInput { caption: String code: String "ISO 3166-1 alpha-2 (uppercase)." origin: String characteristicFormats: [ManufacturerFormatEntryInput!] } "A vendor — WHO SOLD to the merchant: the shared supplier MASTER (group pool), orthogonal to the Manufacturer (who built it). Deliberately thin: contact data is; the org-specific commercial payload (account#, terms, purchasing currency) IS the OrgVendor relationship (the enablement — no purchasing without an active one), arriving. The FIRST procurement-domain construct." type Vendor { id: ID! "The group-scoped human-facing system id (VN-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Vendor parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "Create-input for a Vendor. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here." input NewVendorInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Vendor'; when supplied it must be non-blank." caption: String code: String } "Edit-input for a Vendor. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet)." input EditVendorInput { caption: String code: String } "A category — ONE recursive construct for the whole navigation spectrum (3 flat categories or a 6-level hierarchy; no fixed Department/Subcategory types). inactive = hidden from navigation, still reportable." type Category { id: ID! "The group-scoped human-facing system id (CT-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Category parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The chain always terminates at a root (cycles kit-rejected at write)." treeParent: ID "No further notes." merchandiseDivisionId: ID "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the categories listing — the records + the opaque resume cursor." type CategoryPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Category!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Category. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here." input NewCategoryInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Category'; when supplied it must be non-blank." caption: String code: String "No further notes." treeParent: ID "No further notes." merchandiseDivisionId: ID } "Edit-input for a Category. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. Restructure is exactly this edit: a supplied treeParent is tenant-scoped server-side, must be ACTIVE, and the merged record is walk-validated (a cycle or a chain deeper than 64 is VALIDATION/INVALID naming the offender); the pointers stay mutually exclusive on the MERGED record — re-pointing a division-carrying root under a parent requires clearing the pointer in the SAME edit (never auto-cleared)." input EditCategoryInput { caption: String code: String "No further notes." treeParent: ID "No further notes." merchandiseDivisionId: ID } "A division type: merchandise | geographic | channel. Canned + AT-extensible — a new axis kind is added by the platform, never merchant-defined." enum DivisionType { merchandise geographic channel } "Membership is 0..1 per type per member. Per-org enablement (OrgDivision) arrives; availability semantics (zero geo refs = available everywhere) compose at the Product/assortment slices." type Division { id: ID! "The group-scoped human-facing system id (DV-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Division parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The grouping axis kind — set at creation, IMMUTABLE thereafter." divisionType: DivisionType! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the divisions listing — the records + the opaque resume cursor." type DivisionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Division!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Division. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; divisionType is REQUIRED (the canned registry) and immutable after birth." input NewDivisionInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Division'; when supplied it must be non-blank." caption: String "The grouping axis kind — immutable after birth." divisionType: DivisionType! code: String } "Edit-input for a Division. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). divisionType is NOT editable (immutable at birth, the valueType/dimensionClass precedent). A merchandise Division still pointed at by a non-doomed root Category refuses deactivate AND doom (CONFLICT/REFERENCED naming the blockers, DV-a); release is IMPLICIT — clear or re-point the category pointer (zero Division writes)." input EditDivisionInput { caption: String code: String } "An option-group type: color | size | custom. Canned — a new kind is added by the platform, never merchant-defined." enum OptionGroupType { color size custom } "An option group — the PICK-SOURCE for option dimensions (a size run, a brand color palette), typed from the canned registry (color/size drive the spine tier defaults; custom groups feed descriptive attributes that never explode variants). Holds ordered OptionValue children (their parent). NO org selection ever. Referenced BY Style schemes at the spine." type OptionGroup { id: ID! "The group-scoped human-facing system id (OP-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for an OptionGroup parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The pick-source kind — set at creation, IMMUTABLE thereafter." optionGroupType: OptionGroupType! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String "The dimension DEFAULT SizeRun: the run a style over this group fills its matrix with when it names none of its own; the run must be ACTIVE and over THIS group; set by update only (a run must exist first), EXPLICIT-null-clearable; absent = no default." defaultSizeRunId: ID } "One page of the optionGroups listing — the records + the opaque resume cursor." type OptionGroupPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OptionGroup!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OptionGroup. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; optionGroupType is REQUIRED (the canned registry) and immutable after birth." input NewOptionGroupInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Option group'; when supplied it must be non-blank." caption: String "The pick-source kind — immutable after birth." optionGroupType: OptionGroupType! code: String } "Edit-input for a OptionGroup. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic) — EXCEPT defaultSizeRunId, which additionally accepts an EXPLICIT null to CLEAR. optionGroupType is NOT editable (immutable at birth, OG-a — the divisionType precedent). A group with ACTIVE OptionValue children refuses deactivate; one with NON-doomed children refuses doom (CONFLICT/REFERENCED naming the blockers — bottom-up, children first)." input EditOptionGroupInput { caption: String code: String "The NEW default SizeRun (ACTIVE, over THIS group), or EXPLICIT null to clear; omitted = unchanged." defaultSizeRunId: ID } "An option value — one member of an OptionGroup pick-source (a size cell, a color name), ORDERED via ordinal (lower = earlier in the pick list; ties break by id). Parent = its OptionGroup (NOT the family root — the first non-group-parented catalog construct, the Zone shape). Consumed by the spine (scheme tiers pick values into Product/Variant cells)." type OptionValue { id: ID! "The group-scoped human-facing system id (OV-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent OptionGroup; for an OptionValue parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The pick-list position. Always present (defaults to 0 at create); mutable — reordering is an ordinary edit." ordinal: Int! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the optionValues listing — the records + the opaque resume cursor." type OptionValuePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OptionValue!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OptionValue. The tenant (org group) is derived SERVER-SIDE from the principal; optionGroupId (the parent pick-source) is tenant-scoped server-side and must be active (STRICT — a value may not be born under a non-active group)." input NewOptionValueInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Option value'; when supplied it must be non-blank." caption: String "The parent OptionGroup id." optionGroupId: ID! "Optional pick-list position (0..1000000) — defaults to 0." ordinal: Int code: String } "Edit-input for a OptionValue. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). REORDERING is exactly this edit (a supplied ordinal replaces). The parent-group ref is NOT editable (a value never moves between pick-sources — recreate instead)." input EditOptionValueInput { caption: String ordinal: Int code: String } "An attachable owner type: the constructs a Decoration may attach to at this slice. Grows per slice (Category, OptionValue, Style/Product join at their consuming slices)." enum AttachableType { Brand Season Style Product OptionValue Collection } "A decoration — the ONE purposed, localized, ordered carrier for consumer-facing content, ATTACHED to an owning construct (the decoration carries the attachment; owner records never churn). Purpose comes from the canned registry (text-kind live; MEDIA-kind purposes are refused until the blob mechanics land); locale is canonical BCP-47 (the org-default-locale floor is a resolution-time read rule, later slice); ordinal orders same-purpose content (lower = more important). Decorations are freely doomable (nothing references them); the OWNER doom is blocked by attached non-doomed decorations. inactive = draft/unpublished (content staging)." type Decoration { id: ID! "The group-scoped human-facing system id (DC-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Decoration parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned purpose key. Server-validated (the hyphenated canned keys are not enum-safe); IMMUTABLE after birth." purpose: String! "The content locale — canonical BCP-47 core shape (en, en-US, fr-CA, zh-Hans-CN); case-canonical, STRICT. Mutable." locale: String! "The importance position among same-(owner,purpose,locale) decorations. Always present (defaults to 0 at create); mutable." ordinal: Int! "The inline text content. Mutable, replace-only." text: String! "The owning construct type. IMMUTABLE after birth." attachedToType: AttachableType! "The owning construct id. IMMUTABLE after birth (moving content = recreate)." attachedToId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the decorations listing — the records + the opaque resume cursor." type DecorationPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Decoration!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Decoration. The tenant (org group) is derived SERVER-SIDE from the principal; the attachment target (attachedToType + attachedToId) is tenant-scoped server-side and must be active; purpose must name the canned registry and be text-kind; purpose and the attachment are IMMUTABLE after birth." input NewDecorationInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Decoration'; when supplied it must be non-blank." caption: String "The canned purpose key. Immutable after birth." purpose: String! "The content locale — canonical BCP-47 core shape (case-canonical, STRICT)." locale: String! "Optional importance position (0..1000000; lower = more important) — defaults to 0." ordinal: Int "The inline text content (1..4096 chars)." text: String! "The owning construct type (the attachable allowlist)." attachedToType: AttachableType! "The owning construct id — tenant-scoped server-side, must be active." attachedToId: ID! code: String } "Edit-input for a Decoration. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). purpose / attachedToType / attachedToId are NOT editable (the identity coordinate is immutable at birth, DC-c — moving or re-purposing content = recreate); locale / ordinal / text / code / caption are ordinary replace-only edits." input EditDecorationInput { caption: String locale: String ordinal: Int text: String code: String } "An OrgManufacturer selection — the per-org ENABLEMENT of a group Manufacturer: selection strictly required before any org reference, including purchase lines (the gate). Parent = the ORGANIZATION (not the family root). Freely deactivatable/doomable; a NON-doomed selection blocks the master Manufacturer doom only." type OrgManufacturer { id: ID! "The group-scoped human-facing system id (EM-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a selection parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Manufacturer — set at creation, IMMUTABLE thereafter." manufacturerId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgManufacturers listing — the records + the opaque resume cursor." type OrgManufacturerPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgManufacturer!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OrgManufacturer selection. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and manufacturerId are tenant-scoped server-side and must be active (STRICT)." input NewOrgManufacturerInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Manufacturer'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Manufacturer this selection enables — immutable after birth." manufacturerId: ID! code: String } "Edit-input for a OrgManufacturer. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). manufacturerId is NOT editable (immutable at birth, the selection IS the (org × master) edge; re-pointing = recreate), nor is the parent-org ref (the header)." input EditOrgManufacturerInput { caption: String code: String } "An OrgBrand selection — the per-org ENABLEMENT of a group Brand (the strict-selection pattern: no org-scoped Brand reference without an ACTIVE selection). Parent = the ORGANIZATION (not the family root). Freely deactivatable/doomable; a NON-doomed selection blocks the master Brand doom only." type OrgBrand { id: ID! "The group-scoped human-facing system id (EB-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a selection parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Brand — set at creation, IMMUTABLE thereafter." brandId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgBrands listing — the records + the opaque resume cursor." type OrgBrandPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgBrand!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OrgBrand selection. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and brandId are tenant-scoped server-side and must be active (STRICT)." input NewOrgBrandInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Brand'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Brand this selection enables — immutable after birth." brandId: ID! code: String } "Edit-input for a OrgBrand. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). brandId is NOT editable (immutable at birth, the selection IS the (org × master) edge; re-pointing = recreate), nor is the parent-org ref (the header)." input EditOrgBrandInput { caption: String code: String } "An OrgSeason selection — the per-org ENABLEMENT of a group Season (the strict-selection pattern). Parent = the ORGANIZATION (not the family root). Freely deactivatable/doomable; a NON-doomed selection blocks the master Season doom only." type OrgSeason { id: ID! "The group-scoped human-facing system id (ES-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a selection parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Season — set at creation, IMMUTABLE thereafter." seasonId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgSeasons listing — the records + the opaque resume cursor." type OrgSeasonPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgSeason!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OrgSeason selection. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and seasonId are tenant-scoped server-side and must be active (STRICT)." input NewOrgSeasonInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Season'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Season this selection enables — immutable after birth." seasonId: ID! code: String } "Edit-input for a OrgSeason. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). seasonId is NOT editable (immutable at birth, the selection IS the (org × master) edge; re-pointing = recreate), nor is the parent-org ref (the header)." input EditOrgSeasonInput { caption: String code: String } "An OrgDivision selection — the per-org ENABLEMENT of a group Division, divisionType-AGNOSTIC. Parent = the ORGANIZATION (not the family root). Freely deactivatable/doomable; a NON-doomed selection blocks the master Division doom only." type OrgDivision { id: ID! "The group-scoped human-facing system id (ED-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a selection parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Division — set at creation, IMMUTABLE thereafter." divisionId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgDivisions listing — the records + the opaque resume cursor." type OrgDivisionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgDivision!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OrgDivision selection. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and divisionId are tenant-scoped server-side and must be active (STRICT)." input NewOrgDivisionInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Division'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Division this selection enables (any divisionType — SL-g) — immutable after birth." divisionId: ID! code: String } "Edit-input for a OrgDivision. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). divisionId is NOT editable (immutable at birth, the selection IS the (org × master) edge; re-pointing = recreate), nor is the parent-org ref (the header)." input EditOrgDivisionInput { caption: String code: String } "An OrgVendor — the per-org purchasing ENABLEMENT of a group Vendor: the trio (accountNumber / terms free-text NOTES / purchasingCurrency [STRICT ISO-4217 SHAPE]) + the commercial payload (canned paymentTerms [the shared registry — CANONICAL over the free-text terms] / canned Incoterms-2020 incotermCode / leadTimeDays / the shipTo-LF + billTo/returnsTo-Contact pointers [SL-b set-time gates] / orderMinimum + freeFreightThreshold Money [currency-matched to purchasingCurrency] / requireCatalogItem [the PO-line gate over the OrgVendorItem junction]). Parent = the ORGANIZATION (not the family root). Deactivate stays FREE (pausing the enablement); doom is blocked by live OrgVendorItems; a NON-doomed enablement blocks the master Vendor doom. Money reuses the MoneyEntry SDL (declared on the Product entry)." type OrgVendor { id: ID! "The group-scoped human-facing system id (EV-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for an OrgVendor parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Vendor — set at creation, IMMUTABLE thereafter." vendorId: ID! "The org account number WITH the vendor; optional + editable." accountNumber: String "Free-text terms NOTES." terms: String "The purchasing currency — STRICT ISO-4217 alphabetic SHAPE (three uppercase letters)." purchasingCurrency: String "The canned payment terms; a non-canned token is VALIDATION/INVALID. Optional + editable." paymentTerms: String "The canned Incoterms-2020 delivery term; a non-canned code is VALIDATION/INVALID. Optional + editable." incotermCode: String "The vendor's DEFAULT lead time in days (1..730; the OrgVendorItem may override per item); optional + editable." leadTimeDays: Int "The default ship-to LogicalFacility; optional + editable." defaultShipToLogicalFacilityId: ID "The billing Contact pointer; optional + editable." billToContactId: ID "The return-to-vendor target Contact pointer; optional + editable." returnsToContactId: ID "The order minimum — currency-matched to purchasingCurrency; optional + editable." orderMinimum: MoneyEntry "The free-freight threshold — currency-matched like orderMinimum; optional + editable." freeFreightThreshold: MoneyEntry "Require an OrgVendorItem per PO line (the gate; 's own deliberate default-FALSE). ABSENT (null) on pre- records means FALSE; new records always carry it. Editable." requireCatalogItem: Boolean "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgVendors listing — the records + the opaque resume cursor." type OrgVendorPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgVendor!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OrgVendor. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and vendorId are tenant-scoped server-side and must be active (STRICT), as are the shipTo/billTo/returnsTo pointers when supplied. Every commercial field is optional (the enablement stays creatable thin); orderMinimum/freeFreightThreshold require purchasingCurrency in the SAME payload with a MATCHING currency; requireCatalogItem is stamped FALSE when omitted." input NewOrgVendorInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Vendor'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Vendor this enablement names — immutable after birth." vendorId: ID! accountNumber: String terms: String purchasingCurrency: String "The canned payment-terms token (net-30 · 2-10-net-30 · cod · prepaid)." paymentTerms: String "The canned Incoterms-2020 code (EXW · FCA · CPT · CIP · DAP · DPU · DDP · FAS · FOB · CFR · CIF)." incotermCode: String leadTimeDays: Int defaultShipToLogicalFacilityId: ID billToContactId: ID returnsToContactId: ID "Requires purchasingCurrency in the same payload, with a matching currency." orderMinimum: MoneyEntryInput "Requires purchasingCurrency in the same payload, with a matching currency." freeFreightThreshold: MoneyEntryInput "Defaulted FALSE when omitted." requireCatalogItem: Boolean code: String } "Edit-input for a OrgVendor. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved — EXCEPT the three pointer fields (defaultShipToLogicalFacilityId/billToContactId/returnsToContactId), which additionally accept an EXPLICIT null to CLEAR. vendorId is NOT editable (immutable at birth, the enablement IS the (org × vendor) edge; re-pointing = recreate), nor is the parent-org ref (the header). The FULL commercial payload is editable; supplied non-null pointers re-gate at each set; a supplied money field must match a purchasingCurrency supplied in the SAME edit, and gates against the STORED currency server-side otherwise." input EditOrgVendorInput { caption: String code: String accountNumber: String terms: String purchasingCurrency: String "The canned payment-terms token (net-30 · 2-10-net-30 · cod · prepaid)." paymentTerms: String "The canned Incoterms-2020 code (EXW · FCA · CPT · CIP · DAP · DPU · DDP · FAS · FOB · CFR · CIF)." incotermCode: String leadTimeDays: Int "Supply a LogicalFacility id to re-point (ACTIVE + owned by the buying org), or EXPLICIT null to CLEAR the default." defaultShipToLogicalFacilityId: ID "Supply a Contact id to re-point (ACTIVE-gated), or EXPLICIT null to CLEAR it." billToContactId: ID "Supply a Contact id to re-point (ACTIVE-gated), or EXPLICIT null to CLEAR it." returnsToContactId: ID orderMinimum: MoneyEntryInput freeFreightThreshold: MoneyEntryInput requireCatalogItem: Boolean } "A style type: simple | service | kit | bundle. Canned — a new kind is added by the platform, never merchant-defined. ALL FOUR create everywhere since the component slice: kit/bundle variants bear per-variant VariantComponent BOMs (kit assembles simple components ONLY; bundle groups simple | service | kit)." enum StyleType { simple service kit bundle } "The TaxCategory canned registry (generated from the contracts TAX_CATEGORIES SoT — anti-drift; T-b). AT-maintained, additive-only; the merchant-custom extension is a named deferral. Declared HERE (the first catalog consumer — the MoneyEntry-on-Product precedent); Style classification, TaxRate cells, and ExemptionCertificate scopes all reference it." enum TaxCategory { standard food_grocery prepared_food childrens_clothing clothing prescription_drug medical_device digital_good service } "A scheme tier: product | variant (realizes Variants — the size default)." enum SchemeTier { product variant } "One ordered scheme dimension: the pick-source OptionGroup + the resolved spine tier." type StyleSchemeEntry { optionGroupId: ID! tier: SchemeTier! } "One category placement: the LEAF Category + the optional primary designation (at most 1 primary per style)." type StylePlacementEntry { categoryId: ID! primary: Boolean } "One characteristic VALUE: the Characteristic + this style value for it (validated against the characteristic valueType/grammar server-side)." type StyleCharacteristicEntry { characteristicId: ID! value: String! } "styleType comes from the canned registry (simple | service | kit | bundle — all four realized; kit/bundle variants bear per-variant VariantComponent BOMs since the component slice) and is IMMUTABLE. The scheme is FROZEN once any Product exists. Org availability = the OrgStyle selection; zero dimensions = the corner-store single-cell case." type Style { id: ID! "The group-scoped human-facing system id (ST-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Style parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The style kind — set at creation, IMMUTABLE thereafter." styleType: StyleType! "The ORDERED option-space dimensions. Every stored entry carries its resolved tier; absent/empty = zero dimensions. FROZEN once any Product exists." scheme: [StyleSchemeEntry!] "The optional 0..1 Brand — editable, EXPLICIT-null-clearable; absent = unbranded." brandId: ID "The optional 0..1 SizeRun this style fills its matrix with: the run must be ACTIVE and over a group IN the scheme; editable, EXPLICIT-null-clearable (the brandId CG-a shape); absent = each dimension falls to its group default run, if any. The matrix read (styleStockMatrix) carries the RESOLVED run per axis." sizeRunId: ID "The Season memberships — wholesale-replace list; absent = none." seasonIds: [ID!] "The category placements; wholesale-replace; absent = unplaced." categoryPlacements: [StylePlacementEntry!] "The Tag set — wholesale-replace list; absent = untagged." tagIds: [ID!] "The characteristic VALUES; wholesale-replace; absent = none." characteristicEntries: [StyleCharacteristicEntry!] "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String "The tax classification (the canned TaxCategory registry; T-j) — ABSENT = standard (the default; revert = set 'standard'). Editable. The flagged Product-level override stays deferred." taxCategory: TaxCategory } "One page of the styles listing — the records + the opaque resume cursor." type StylePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Style!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Scheme-dimension input — tier may be omitted for color/size groups (defaulted product/variant respectively); a custom-typed group REQUIRES an explicit tier." input StyleSchemeEntryInput { optionGroupId: ID! tier: SchemeTier } "Category-placement input — the target must be an in-tenant, ACTIVE, LEAF Category." input StylePlacementEntryInput { categoryId: ID! primary: Boolean } "Characteristic-value input — the target must be in-tenant + active; the value must fit its valueType/grammar." input StyleCharacteristicEntryInput { characteristicId: ID! value: String! } "Create-input for a Style. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; styleType is REQUIRED (all four types accepted — the refusal lifted) and immutable; every referenced construct (scheme groups / brand / seasons / placement categories [LEAF-only] / tags / characteristics [value-validated]) is tenant-scoped server-side and must be ACTIVE." input NewStyleInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Style'; when supplied it must be non-blank." caption: String "The style kind — immutable after birth; all four types accepted." styleType: StyleType! "The ORDERED option dimensions (at most 8, unique groups; tier defaulted for color/size, REQUIRED for custom)." scheme: [StyleSchemeEntryInput!] "The optional Brand — tenant-scoped server-side, must be active." brandId: ID "The optional SizeRun — tenant-scoped server-side, must be ACTIVE and over a group in the scheme." sizeRunId: ID "Season memberships (at most 32, unique) — each tenant-scoped + active." seasonIds: [ID!] "Category placements (at most 32, unique, at most 1 primary) — each target tenant-scoped + active + a LEAF." categoryPlacements: [StylePlacementEntryInput!] "The Tag set (at most 64, unique) — each tenant-scoped + active." tagIds: [ID!] "Characteristic values (at most 64, unique per characteristic) — each target tenant-scoped + active; values validated per valueType/grammar." characteristicEntries: [StyleCharacteristicEntryInput!] code: String "The tax classification — ABSENT = standard (the default)." taxCategory: TaxCategory } "Edit-input for a Style. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. brandId and sizeRunId additionally accept an EXPLICIT null to CLEAR; every supplied LIST replaces WHOLESALE (the MF-d precedent — an empty list releases), re-gated per entry exactly like create. styleType is NOT editable (immutable at birth). A supplied scheme is FROZEN-gated: once the style has any Product it is refused CONFLICT/REFERENCED naming them." input EditStyleInput { caption: String code: String "The replacement scheme (wholesale) — REFUSED once any Product exists." scheme: [StyleSchemeEntryInput!] "The NEW Brand pointer, or EXPLICIT null to clear; omitted = unchanged." brandId: ID "The NEW SizeRun pointer (ACTIVE, over a group in the scheme), or EXPLICIT null to clear; omitted = unchanged." sizeRunId: ID "The replacement season set (wholesale; empty releases)." seasonIds: [ID!] "The replacement placements (wholesale; empty releases)." categoryPlacements: [StylePlacementEntryInput!] "The replacement tag set (wholesale; empty releases)." tagIds: [ID!] "The replacement characteristic values (wholesale; empty releases)." characteristicEntries: [StyleCharacteristicEntryInput!] "The classification — revert = set 'standard' (absent means standard; no null-clear)." taxCategory: TaxCategory } "One declared segment dimension: a scheme dimension + the OptionValues this product claims for it (unique, at most 256)." type ProductSegmentEntry { optionGroupId: ID! optionValueIds: [ID!]! } "One money-map entry: an ISO-4217-shape currency + a strict decimal-STRING amount (never a float; stored and compared verbatim; no arithmetic)." type MoneyEntry { currency: String! amount: String! } "Parent = its Style (NOT the family root — the spine containment). The declared SEGMENT constrains any subset of the scheme dimensions (omitted dims unconstrained; empty = the WHOLE style); declared sibling overlap is ALLOWED — disjointness is enforced at the CELL. Money amounts are strict decimal STRINGS (no float ever, no arithmetic); rrp is REQUIRED with at least one entry and floor-gated under live selections." type Product { id: ID! "The group-scoped human-facing system id (PD-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Style; for a Product parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The declared segment — per-dimension claimed values; absent/empty = the WHOLE style. Wholesale-replace; edits may not orphan existing variants (CONFLICT/REFERENCED naming them)." segment: [ProductSegmentEntry!] "The RRP money map. Wholesale-replace; floor-gated under live selections." rrp: [MoneyEntry!]! "The optional MSRP money map; wholesale-replace; absent = none." msrp: [MoneyEntry!] "The Tag set — wholesale-replace list; absent = untagged." tagIds: [ID!] "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the products listing — the records + the opaque resume cursor." type ProductPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Product!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Segment-dimension input — the dimension must be IN the parent style scheme; every value must belong to that dimension group and be ACTIVE." input ProductSegmentEntryInput { optionGroupId: ID! optionValueIds: [ID!]! } "Money-entry input — currency: three uppercase letters (ISO-4217 shape); amount: a strict decimal string (at most 12 integer digits, at most 4 fraction digits, no leading zeros)." input MoneyEntryInput { currency: String! amount: String! } "Create-input for a Product. The tenant (org group) is derived SERVER-SIDE from the principal; styleId (the parent Style — rides the header) is tenant-scoped server-side and must be active (STRICT); every segment dimension must be in the style scheme with values of that group, ACTIVE at declaration; rrp is REQUIRED (at least 1 entry) and — when the style has live OrgStyle selections — must cover every selecting org defaultCurrency (CONFLICT/CURRENCY_FLOOR, site 2)." input NewProductInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Product'; when supplied it must be non-blank." caption: String "The parent Style id." styleId: ID! "The declared segment (omit or empty = the WHOLE style; unique dimensions; values in-scheme + of-the-group + active)." segment: [ProductSegmentEntryInput!] "The RRP map — REQUIRED, at least 1 entry." rrp: [MoneyEntryInput!]! "The optional MSRP map." msrp: [MoneyEntryInput!] "The Tag set (at most 64, unique) — each tenant-scoped + active." tagIds: [ID!] code: String } "Edit-input for a Product. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. The parent-style ref is NOT editable (the header — recreate instead). A supplied segment replaces WHOLESALE and may not orphan: every existing non-doomed variant coordinate must remain inside the new segment (CONFLICT/REFERENCED naming the variants). A supplied rrp replaces WHOLESALE but must keep at least 1 entry and — under live OrgStyle selections — must still cover every selecting org defaultCurrency (CONFLICT/CURRENCY_FLOOR, site 2); msrp/tagIds replace wholesale (empty releases — the MF-d precedent)." input EditProductInput { caption: String code: String "The replacement segment (wholesale) — no-orphan-gated against existing variants." segment: [ProductSegmentEntryInput!] "The replacement RRP map (wholesale; at least 1 entry; floor-gated)." rrp: [MoneyEntryInput!] "The replacement MSRP map (wholesale; empty releases)." msrp: [MoneyEntryInput!] "The replacement tag set (wholesale; empty releases)." tagIds: [ID!] } "A stock-UoM kind: canned (a platform UoM code like each) | custom (an in-tenant CustomUom)." enum StockUomKind { canned custom } "One coordinate entry: a scheme dimension + the ONE OptionValue this cell realizes for it." type VariantCoordinateEntry { optionGroupId: ID! optionValueId: ID! } "One manufacturer part number — THAT manufacturer's token for THIS variant (their part number, not our SKU)." type ManufacturerPartNumber { manufacturerId: ID! partNumber: String! } "A variant — the spine LEAF, the SELLABLE CELL: one complete coordinate of its Style option space (every scheme dimension exactly once) and the SKU bearer (IdentifierEntry lands; inventory). Parent = its Product (NOT the family root). The coordinate is IMMUTABLE at birth — a cell IS its coordinate; re-coordinate = recreate. Cell DISJOINTNESS is the ratified: a per-(style × cell) uniqueness marker minted in the create transaction — a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holding variant AND its product; a doomed holder is taken over. The stock-UoM pair (stockUomKind, stockUomRef) defaults (canned, each) and is IMMUTABLE." type Variant { id: ID! "The group-scoped human-facing system id (VR-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Product; for a Variant parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The COMPLETE cell coordinate — every scheme dimension exactly once, stored in scheme order; empty = the zero-dimension cell. IMMUTABLE at birth." coordinate: [VariantCoordinateEntry!]! "The stock-UoM kind; IMMUTABLE at birth, paired with stockUomRef." stockUomKind: StockUomKind! "The stock-UoM ref — a canned UoM code (each, …) or a CustomUom id per the kind; IMMUTABLE at birth." stockUomRef: String! "The manufacturer part-number map; absent when none. MUTABLE — a supplied list REPLACES wholesale." manufacturerPartNumbers: [ManufacturerPartNumber!] "Optional mutable merchant reference code; uniqueness NOT enforced (the code stance)." code: String } "One page of the variants listing — the records + the opaque resume cursor." type VariantPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Variant!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Coordinate-entry input — order-insensitive; the full coordinate must name EVERY scheme dimension exactly once with an active value of that group, inside the product segment where constrained." input VariantCoordinateEntryInput { optionGroupId: ID! optionValueId: ID! } "Manufacturer part-number input — each manufacturerId tenant-scoped server-side + ACTIVE; at most 8 entries, unique per manufacturer; a supplied list REPLACES the stored map wholesale." input ManufacturerPartNumberInput { manufacturerId: ID! partNumber: String! } "Create-input for a Variant. The tenant (org group) is derived SERVER-SIDE from the principal; productId (the parent Product — rides the header) is tenant-scoped server-side and must be active; the coordinate must realize EVERY scheme dimension exactly once (active values, of the dimension group, inside the product segment where constrained) and is IMMUTABLE; a custom stock-UoM ref is tenant-scoped + active-gated; the stock-UoM pair defaults (canned, each). The (style × cell) marker is minted IN the create transaction — a live duplicate is CONFLICT/IDENTITY_TAKEN naming holder + holderProduct; a doomed holder is taken over (the ratified)." input NewVariantInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Variant'; when supplied it must be non-blank." caption: String "The parent Product id." productId: ID! "The cell coordinate (omit for a zero-dimension style; must realize every scheme dimension exactly once)." coordinate: [VariantCoordinateEntryInput!] "The stock-UoM kind — defaults to canned; immutable after birth." stockUomKind: StockUomKind "The stock-UoM ref — defaults to each; a canned code, or a CustomUom id for kind custom; immutable after birth." stockUomRef: String "The manufacturer part-number map — each manufacturer server-gated in-tenant + ACTIVE; at most 8, unique per manufacturer." manufacturerPartNumbers: [ManufacturerPartNumberInput!] code: String } "Edit-input for a Variant. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). The coordinate AND the stock-UoM pair are NOT editable (IMMUTABLE at birth, / — a cell IS its coordinate; re-coordinate or re-UoM = recreate), nor is the parent-product ref (the header). Caption/code are ordinary edits; a supplied manufacturerPartNumbers list REPLACES the stored map wholesale." input EditVariantInput { caption: String code: String "The replacement part-number map (wholesale; at most 8, unique per manufacturer; each manufacturer re-gated)." manufacturerPartNumbers: [ManufacturerPartNumberInput!] } "An OrgStyle selection — the per-org ENABLEMENT of a group Style: selection strictly required before the org ranges/sells it. Parent = the ORGANIZATION (not the family root). NO domain payload (per-org assortment/pricing enrichments arrive additively at their own slices). Freely deactivatable/doomable; a NON-doomed selection blocks the master Style doom only. Creating one is floor-gated: the org must HAVE a defaultCurrency and every non-doomed Product of the style must price it (CONFLICT/CURRENCY_FLOOR, site 1)." type OrgStyle { id: ID! "The group-scoped human-facing system id (EY-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a selection parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Style — set at creation, IMMUTABLE thereafter." styleId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgStyles listing — the records + the opaque resume cursor." type OrgStylePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgStyle!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an OrgStyle selection. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and styleId are tenant-scoped server-side and must be active (STRICT); the currency floor gates the create." input NewOrgStyleInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Style'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Style this selection enables — immutable after birth." styleId: ID! code: String } "Edit-input for a OrgStyle. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). styleId is NOT editable (immutable at birth, the selection IS the (org × master) edge; re-pointing = recreate), nor is the parent-org ref (the header)." input EditOrgStyleInput { caption: String code: String } "A product relation — a TYPED, DIRECTED, RANKED suggestion edge between two Products (alternative | replacement | accessory | upsell | cross-sell — canned, AT-extensible). Parent = the SOURCE Product (relations die with their source); the TARGET is gate-protected from doom while suggested. Directed by design — symmetric intent = create both directions. Relation identity (source x target x relationType) is unique (a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holder; a doomed one is taken over). Variant-level matching is DERIVED at read time — a later read-side slice." type ProductRelation { id: ID! "The group-scoped human-facing system id (PR-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent SOURCE Product; for a ProductRelation parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The suggested TARGET Product — set at creation, IMMUTABLE thereafter." targetProductId: ID! "The canned relation type — set at creation, IMMUTABLE thereafter." relationType: String! "The suggestion rank. Mutable — reordering is an ordinary edit." ordinal: Int! } "One page of the productRelations listing — the records + the opaque resume cursor." type ProductRelationPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ProductRelation!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a ProductRelation. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; sourceProductId (the parent — rides the header) and targetProductId are tenant-scoped server-side and must be ACTIVE; self-relation is refused; relationType must be a registered kind (the NAMED gate runs before parse)." input NewProductRelationInput { "Optional: when omitted the per-type default applies — the relation type (a relation carries no merchant code); when supplied it must be non-blank." caption: String "The SOURCE Product id." sourceProductId: ID! "The TARGET Product id — immutable after birth; self-relation refused." targetProductId: ID! "The canned relation type — immutable after birth; unknown kinds refused by the NAMED gate." relationType: String! "The suggestion rank (LOWER = FIRST; 0..1000000) — defaulted to 0 when omitted." ordinal: Int } "Edit-input for a ProductRelation. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). targetProductId and relationType are NOT editable (IMMUTABLE relation identity, RC-c — re-point = doom + create; the uniqueness marker never swaps)." input EditProductRelationInput { caption: String "The replacement suggestion rank (LOWER = FIRST; 0..1000000)." ordinal: Int } "A collection type: static (curated member records) | dynamic (predicate-driven, evaluation deferred). Canned — chosen at birth, immutable." enum CollectionType { static dynamic } "The dynamic-collection price axis — inclusive bounds over ONE currency of the Product rrp map; strict decimal STRINGS (the money grammar), compared verbatim (no float ever)." type CollectionPriceBound { currency: String! min: String max: String } "One dynamic-collection characteristic match: the Characteristic + the matched value (validated against its valueType/grammar server-side). Multiple entries per characteristic = OR within the axis." type CollectionCharacteristicPredicate { characteristicId: ID! value: String! } "THE DYNAMIC-COLLECTION PREDICATE. Semantics: AND across supplied axes, OR within an axis, categoryIds match SUBTREES, exclusions subtract, pins union first. At least one axis is required." type CollectionPredicate { "Category refs — SUBTREE semantics at evaluation (at most 32, unique)." categoryIds: [ID!] "Tag refs (at most 64, unique)." tagIds: [ID!] "Brand refs (at most 32, unique)." brandIds: [ID!] "Season refs (at most 32, unique)." seasonIds: [ID!] "Division refs (at most 32, unique)." divisionIds: [ID!] "The price axis — bounds over ONE currency." price: CollectionPriceBound "The characteristic axis (at most 64, unique pairs)." characteristics: [CollectionCharacteristicPredicate!] } "A collection — a consumer-facing curated or rule-driven grouping of Products (gift guides, seasonal edits). collectionType is canned + IMMUTABLE at birth: static = curated CollectionMember child records; dynamic = membership DERIVED from the stored predicate (stored + validated; EVALUATION is a deferred read-model slice, nothing evaluates yet). Member records on a dynamic collection are its PINS (manual-pins-first). inactive = STAGED/unpublished. NO per-org selection construct exists; decorations are first-class." type Collection { id: ID! "The group-scoped human-facing system id (CL-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Collection parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned collection kind — set at creation, IMMUTABLE thereafter." collectionType: CollectionType! "The dynamic predicate. AND across supplied axes, OR within an axis; categoryIds match SUBTREES; evaluation is the deferred slice." predicate: CollectionPredicate "Manual exclusions; wholesale-replace (an empty list releases); write-time-validated Product refs." excludedProductIds: [ID!] "The canned sort mode. DYNAMIC only; stamped newest at create when omitted." sortMode: String "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the collections listing — the records + the opaque resume cursor." type CollectionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Collection!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Price-axis input — at least one bound; min must not exceed max (decimal-string comparison, no float)." input CollectionPriceBoundInput { currency: String! min: String max: String } "Characteristic-match input — the target must be in-tenant + active; the value must fit its valueType/grammar." input CollectionCharacteristicPredicateInput { characteristicId: ID! value: String! } "The predicate input." input CollectionPredicateInput { categoryIds: [ID!] tagIds: [ID!] brandIds: [ID!] seasonIds: [ID!] divisionIds: [ID!] price: CollectionPriceBoundInput characteristics: [CollectionCharacteristicPredicateInput!] } "Create-input for a Collection. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; collectionType is REQUIRED + immutable; a STATIC create refuses predicate/excludedProductIds/sortMode (the NAMED cross-type gate); a DYNAMIC create REQUIRES a predicate (≥1 axis) and stamps sortMode newest when omitted; every predicate/exclusion ref is tenant-scoped server-side and must be ACTIVE." input NewCollectionInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Collection'; when supplied it must be non-blank." caption: String "The canned collection kind — immutable after birth." collectionType: CollectionType! "The predicate — REQUIRED on dynamic (≥1 axis), REFUSED on static (the NAMED gate)." predicate: CollectionPredicateInput "Manual exclusions (at most 256, unique) — dynamic only; each tenant-scoped + active." excludedProductIds: [ID!] "The canned sort mode (newest | price-asc | price-desc | manual-pins-first) — dynamic only; defaulted newest." sortMode: String code: String } "Edit-input for a Collection. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. A supplied predicate replaces WHOLESALE (it can never be cleared — a dynamic collection always carries one) and is re-gated per ref exactly like create; excludedProductIds replaces wholesale (an empty list releases); sortMode replaces (never cleared — it has a birth default). collectionType is NOT editable (immutable at birth). The dynamic-only fields are REFUSED on a STATIC collection (the NAMED cross-type gate, RC-h)." input EditCollectionInput { caption: String code: String "The replacement predicate (wholesale; ≥1 axis) — dynamic collections only." predicate: CollectionPredicateInput "The replacement exclusion list (wholesale; an empty list releases) — dynamic only." excludedProductIds: [ID!] "The replacement sort mode (canned) — dynamic only." sortMode: String } "A collection member — ONE curated membership edge: a Product with a display ordinal inside a Collection. Parent = the Collection (members die with it). On a STATIC collection the members ARE the membership; on a DYNAMIC one they are the PINS (manual-pins-first — RC-o). Membership (collection x product) is unique (a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holder); REMOVE = doom (TWO_STATE — history preserved); re-adding mints a NEW record via marker takeover." type CollectionMember { id: ID! "The group-scoped human-facing system id (CM-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent Collection; for a CollectionMember parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The member Product — set at creation, IMMUTABLE thereafter." productId: ID! "The display order. Mutable — reordering is an ordinary edit." ordinal: Int! } "One page of the collectionMembers listing — the records + the opaque resume cursor." type CollectionMemberPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CollectionMember!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a CollectionMember. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; collectionId (the parent — rides the header) and productId are tenant-scoped server-side and must be ACTIVE." input NewCollectionMemberInput { "Optional: when omitted the per-type default applies — the constant 'CollectionMember' (a membership edge carries no merchant code); when supplied it must be non-blank." caption: String "The owning Collection id." collectionId: ID! "The member Product id — immutable after birth." productId: ID! "The display order (LOWER = FIRST; 0..1000000) — defaulted to 0 when omitted." ordinal: Int } "Edit-input for a CollectionMember. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). productId is NOT editable (IMMUTABLE membership identity, RC-o — re-point = doom + create; the uniqueness marker never swaps)." input EditCollectionMemberInput { caption: String "The replacement display order (LOWER = FIRST; 0..1000000)." ordinal: Int } "A variant component — ONE bill-of-materials edge: quantity units of a COMPONENT Variant inside a kit/bundle HOST Variant. Parent = the HOST Variant (components die with it). The coupling matrix gates creation: a kit assembles simple component variants ONLY; a bundle groups simple | service | kit (never bundles — acyclic BY TYPE). Composition (host x component) is unique (a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holder); REMOVE = doom (TWO_STATE — history preserved); re-adding mints a NEW record via marker takeover. BUILD/BREAK stock semantics + assembly-mode policy evaluation are consumers of this stored shape." type VariantComponent { id: ID! "The group-scoped human-facing system id (VC-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent HOST Variant; for a VariantComponent parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The COMPONENT Variant — set at creation, IMMUTABLE thereafter." componentVariantId: ID! "Whole units of the component per ONE host unit (1..1000000). Mutable — the quantity change is an ordinary edit." quantity: Int! } "One page of the variantComponents listing — the records + the opaque resume cursor." type VariantComponentPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [VariantComponent!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a VariantComponent. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; variantId (the HOST — rides the header) and componentVariantId are tenant-scoped server-side; the host must be non-doomed and kit/bundle-typed, the component ACTIVE and coupling-admitted (kit ← simple only; bundle ← simple | service | kit — the NAMED gates)." input NewVariantComponentInput { "Optional: when omitted the per-type default applies — the constant 'VariantComponent' (a composition edge carries no merchant code); when supplied it must be non-blank." caption: String "The HOST (kit/bundle) Variant id." variantId: ID! "The COMPONENT Variant id — immutable after birth; self-composition refused." componentVariantId: ID! "Whole units per ONE host unit (1..1000000) — defaulted to 1 when omitted." quantity: Int } "Edit-input for a VariantComponent. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). componentVariantId is NOT editable (IMMUTABLE composition identity, KB-c — re-point = doom + create; the uniqueness marker never swaps)." input EditVariantComponentInput { caption: String "The replacement quantity (whole units per ONE host unit; 1..1000000)." quantity: Int } "An inventory item: ONE per (Variant x LogicalFacility), carrying the CACHED bucket balances + the weighted-moving-average cost. Parent = the Variant; the other junction leg is the IMMUTABLE logicalFacilityId. The junction (variant x LF) is unique (a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holder). styleType is BIRTH-STAMPED from the spine (immutable upstream): simple/kit IIs are STOCKED; service/bundle IIs are STOCKLESS price-carriers refusing quantity movements. Buckets are SIGNED decimal strings moved ONLY by the movement ops (receiveStock/adjustStock/reclassStock: one movement = ONE transaction; overcommit is allowed + ALWAYS evented, IV-i); available = on_hand − reserved, ALWAYS derived, never stored. Doom requires EVERY bucket exactly zero (CONFLICT/REFERENCED naming the non-zero buckets); deactivate is FREE and reversible. onOrderQty is a SIXTH field, NOT a bucket: the open quantity of the issued purchase orders for this junction, maintained by the purchase-order walks + the receipt post — never by movements, never inside available; a pre-walk row reads 0; the audit/repair pair (inventoryOnOrderAudit / repairInventoryOnOrder) stamps the derived truth over drift." type InventoryItem { id: ID! "The group-scoped human-facing system id (IV-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Variant; for an InventoryItem parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The LogicalFacility leg of the junction — set at creation, IMMUTABLE thereafter." logicalFacilityId: ID! "The BIRTH-STAMPED spine styleType: simple | service | kit | bundle; service/bundle IIs are stockless price-carriers." styleType: String! "The control class (canned: non-controlled | lot-controlled | serially-controlled — server-validated, the DC-d shape). Mutable — an ordinary edit." controlClass: String! "The CACHED on_hand balance — a SIGNED decimal string; moves ONLY via movements." onHandQty: String! "The CACHED reserved claim overlay." reservedQty: String! "The CACHED in_transit balance (the transfer saga — zero until that slice)." inTransitQty: String! "The CACHED damaged balance." damagedQty: String! "The CACHED held balance (reason-coded via the movement entries)." heldQty: String! "On order — the issued purchase orders’ open quantity for this item: maintained by the purchase-order walks (+ at issue/approve, − at cancel, − the open remainder at close_short) and the receipt post (− the arriving quantity); NOT part of available; every decrement clamps at 0. A pre-walk row reads 0; the audit/repair pair (inventoryOnOrderAudit / repairInventoryOnOrder) stamps the derived truth over any drift." onOrderQty: String! "DERIVED, never stored: on_hand − reserved, computed at read time (exact decimal-string arithmetic)." availableQty: String! "The weighted-moving-average unit cost. Absent until the first costed receive." wmaCost: MoneyEntry } "Create-input for an InventoryItem. The tenant (org group) is derived SERVER-SIDE from the principal; variantId (rides the header) and logicalFacilityId are tenant-scoped server-side and must both be ACTIVE (CONFLICT/REF_STATE else); styleType is birth-stamped from the variant spine; the buckets are born zero x5 and wmaCost absent — quantities move ONLY via the movement ops." input NewInventoryItemInput { "Optional: when omitted the per-type default applies — the junction coordinate ` @ `; when supplied it must be non-blank." caption: String "The stock-bearing Variant id." variantId: ID! "The LogicalFacility id (the other junction leg) — immutable after birth." logicalFacilityId: ID! "The control class (non-controlled | lot-controlled | serially-controlled) — defaulted to non-controlled when omitted (STRICT)." controlClass: String } "Edit-input for a InventoryItem. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). logicalFacilityId and styleType are NOT editable (IMMUTABLE junction identity/birth stamp); the buckets and wmaCost are NOT here AT ALL — they move ONLY via the movement transactions." input EditInventoryItemInput { caption: String "The replacement control class (non-controlled | lot-controlled | serially-controlled — server-validated)." controlClass: String } "A sale price: ONE effective-dated price window in the parent InventoryItem schedule — the dated record-set IS the full price history. Windows are half-open [startAt, endAt) with endAt ALWAYS present (far-future = the standing price); past the last endAt with no successor the item is NOT for sale (the LAPSE rule — enforced by the sell path; stores + normalizes). Inserts are splice-normalized: a start falling STRICTLY inside the immediately-preceding window auto-TRIMS that predecessor endAt to the new start (the ONE sanctioned in-place mutation — revisioned + evented); overlap with ANY OTHER record refuses CONFLICT/PRICE_WINDOW_OVERLAP naming the blockers. No past starts. The schedule currency is FIXED by the FIRST record; a mismatch is refused NAMED. Doom cancels a not-yet-effective FUTURE record only. startAt/endAt/price are wire-IMMUTABLE." type SalePrice { id: ID! "The group-scoped human-facing system id (SP-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent InventoryItem; for a SalePrice parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The window start (INCLUSIVE; UTC ISO-8601) — set at birth (absent in the create input = effective NOW, server-stamped), IMMUTABLE thereafter." startAt: String! "The window end (EXCLUSIVE; UTC ISO-8601; ALWAYS present). Moves ONLY via the system splice trim when a successor starts inside this window." endAt: String! "The selling price for the window (the strict decimal-string money grammar; the schedule currency is FIXED by the FIRST record). IMMUTABLE — supersede to change." price: MoneyEntry! "The MarkdownPlan whose schedule fan-out wrote this window." markdownPlanId: ID "The 0-based step within the stamping plan's cadence." markdownStepIndex: Int } "One page of the salePrices listing — the records + the opaque resume cursor." type SalePricePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [SalePrice!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a SalePrice. The tenant (org group) is derived SERVER-SIDE from the principal; inventoryItemId (rides the header) is tenant-scoped server-side and must be NON-doomed; startAt is optional (absent = effective NOW, server-stamped; explicit values must be >= the server now — no past starts) and must precede endAt; the price currency must match the schedule fixed currency (the first record fixes it)." input NewSalePriceInput { "Optional: when omitted the per-type default applies — the window coordinate ` from `; when supplied it must be non-blank." caption: String "The InventoryItem id." inventoryItemId: ID! "The window start (INCLUSIVE; UTC ISO-8601). Optional — absent = effective NOW (server-stamped); explicit values must be >= the server now." startAt: String "The window end (EXCLUSIVE; UTC ISO-8601). ALWAYS required; must be strictly after startAt." endAt: String! "The selling price — the currency must match the schedule fixed currency." price: MoneyEntryInput! } "Edit-input for a SalePrice. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). startAt, endAt and price are NOT editable (wire-IMMUTABLE window facts, supersede with a new window or doom a FUTURE record and re-create; the system splice trim is the ONE sanctioned endAt move)." input EditSalePriceInput { caption: String } "One embedded Transfer line." type TransferLine { "1-based position (create input order) — the receipt/resolution addressing key." lineNo: Int! "The SOURCE InventoryItem id (variant x source LF)." inventoryItemId: ID! "The DESTINATION InventoryItem id (same variant x destination LF) — server-resolved at create (IV-b: the junction must already exist; movements never auto-vivify)." destinationInventoryItemId: ID! "The variant both junctions share (provenance — server-resolved at create)." variantId: ID! "The quantity to move (decimal string, stock UoM, strictly positive)." quantity: String! "The carried unit cost — birth-stamped at SHIP from the source WMA; absent until then, and absent forever on an un-costed source book." unitCost: MoneyEntry "Rollup: quantity shipped (a light transfer stamps it at its one completing step)." shippedQty: String! "Rollup: quantity landed at the destination (on_hand + held together)." receivedQty: String! "Rollup: the held subset of receivedQty (quarantine landings)." heldQty: String! "Rollup: residual quantity disposed via resolve (disposition-coded doc-referencing movements)." resolvedQty: String! "Rollup: DECLARED surplus booked at receive (the accepted-unplanned lane, absent = 0). OUTSIDE receivedQty by design — the over-receipt outstanding math stays pure." unplannedQty: String "The originating TransferRequest — present iff this Transfer was born by an acceptance." transferRequestId: ID "The originating request line number (1-based on THAT doc) — travels with transferRequestId." requestLineNo: Int } "A stock transfer: ONE shipment event moving stock between two LogicalFacilities of the SAME org group (the never-cross-group law IS the tenancy boundary; the source and destination ORGS may differ = intercompany, attribution stamped at birth). LIGHT weight (same physical location — birth-derived from the LF-PF-PFL spine) completes in the ONE submit step (no reserve, no in_transit). Cancel is pre-ship ONLY; cancelled is the ONE doomed terminal (lists filter it); completed/closed are IMMUTABLE non-doomed history — a write there refuses CONFLICT/IMMUTABLE." type Transfer { id: ID! "The group-scoped human-facing system id (TF-…)." sysId: String! type: String! caption: String! "The FSM state: draft | pending_send_approval | ready | in_transit | pending_receive_approval | partially_received | received | in_dispute | completed | closed | cancelled." status: String! "The parent SOURCE LogicalFacility; for a Transfer parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The destination LogicalFacility (pointer ref; never the parent — a same-LF pair is a relocation, refused at birth: relocateStock is the doc-less sibling)." destinationLogicalFacilityId: ID! "The transfer weight — light (same PFL: immediate handoff, no in_transit) or shipped (the full saga). BIRTH-DERIVED from the live LF-PF-PFL spine and IMMUTABLE." weight: String! "The source LF owning org (spine-derived at birth — the PF parent; intercompany attribution). IMMUTABLE." sourceOrganizationId: ID! "The destination LF owning org (spine-derived at birth; == sourceOrganizationId for intra-org moves). IMMUTABLE." destinationOrganizationId: ID! "The expected arrival instant (UTC ISO-8601; shipped metadata — drives the future in-transit aging strand). Lands at SHIP, absent before." expectedArrivalAt: String "Carrier / tracking references. Land at SHIP, absent before." carrierRefs: [String!] "The EMBEDDED lines." lines: [TransferLine!]! } "One page of the transfers listing — the records + the opaque resume cursor." type TransferPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Transfer!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for a Transfer. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). A write while the doc rests in an immutable terminal (completed / closed / cancelled) refuses CONFLICT/IMMUTABLE." input EditTransferInput { caption: String } "One embedded TransferRequest line." type TransferRequestLine { "1-based position (create input order) — the accept/reject addressing key." lineNo: Int! "The requested variant." variantId: ID! "The REQUESTING-LF InventoryItem junction (variant x requesting LF) — server-resolved + stamped at create." destinationInventoryItemId: ID! "The requested quantity (decimal string, stock UoM, strictly positive)." quantity: String! "Rollup: total accepted quantity across LIVE allocations (a cancelled linked Transfer un-allocates — TR-c)." allocatedQty: String! "Rollup: total shipped by linked Transfers (stamped in the linked ship transaction)." shippedQty: String! "Rollup: total received at the requesting LF (on_hand + held together; stamped in the linked receive transaction)." receivedQty: String! "DERIVED: requested minus received — never stored (the availableQty stance)." outstandingQty: String! "The acceptance ledger (max 8 LIVE rows per line — one per linked Transfer; TR-o)." allocations: [TransferRequestAllocation!]! "The decline markers (max 8 per line — one per declining source; TR-h)." declines: [TransferRequestDecline!]! "The special_order demand line this TR line sources." orderLineRef: SpecialOrderLineRef } "One allocation row: the record of ONE acceptance = ONE linked Transfer born ready at the accepting source. The reservation itself is TRANSFER-owned — the request never holds claims." type TransferRequestAllocation { "The accepting SOURCE LogicalFacility." sourceLogicalFacilityId: ID! "The SOURCE InventoryItem (variant x source LF — resolved at accept, TR-g)." sourceInventoryItemId: ID! "The linked Transfer born by this acceptance (its lines carry the back-refs — TR-b)." transferId: ID! "The quantity this acceptance allocated (== the born Transfer line quantity)." allocatedQty: String! } "One decline marker." type TransferRequestDecline { "The declining SOURCE LogicalFacility." sourceLogicalFacilityId: ID! "Optional free-text reason." reason: String } "The canned request priorities." enum TransferRequestPriority { low normal high urgent } "A stock transfer request: a requesting LF asks variants x quantities of the group (open sourcing) or of ONE targeted source LF. Lines are EMBEDDED, VARIANT-keyed + birth-fixed (max 24 — TR-o); cancelled is the ONE doomed terminal (lists filter it); fulfilled/closed_short are IMMUTABLE non-doomed history — a write there refuses CONFLICT/IMMUTABLE." type TransferRequest { id: ID! "The group-scoped human-facing system id (TR-…)." sysId: String! type: String! caption: String! "The FSM state: draft | submitted | open | fulfilled | closed_short | cancelled." status: String! "The parent REQUESTING LogicalFacility; for a TransferRequest parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The requesting LF owning org (spine-derived at birth — the attribution symmetry, demand side; sources attribute themselves on the born Transfers). IMMUTABLE." requestingOrganizationId: ID! "The TARGETED source LF; ABSENT = open to the group. Only the target may accept/reject a targeted request. BIRTH-FIXED." targetLogicalFacilityId: ID "The needed-by instant (UTC ISO-8601; demand metadata — priority-driven sourcing views are a catalogued later read). BIRTH-FIXED." neededBy: String "The canned request priority. BIRTH-FIXED." priority: TransferRequestPriority "The EMBEDDED lines. The rollup counters + allocation rows mutate ONLY via accept / linked-Transfer steps under the doc OCC." lines: [TransferRequestLine!]! } "One page of the transferRequests listing — the records + the opaque resume cursor." type TransferRequestPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TransferRequest!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for a TransferRequest. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). The requesting/target LFs, the demand metadata (neededBy / priority) and the lines are BIRTH-FIXED; the rollups + allocation rows mutate ONLY via accept / linked-Transfer steps. A write while the doc rests in an immutable terminal (fulfilled / closed_short / cancelled) refuses CONFLICT/IMMUTABLE." input EditTransferRequestInput { caption: String } "The canned count types." enum CountType { physical cycle spot } "The scope SELECTOR: at most ONE location axis (whole-LF when both arrays are absent | zones | bins) plus the optional control-class II filter; the join-walk attribute filters (category/division/tag/brand) are the.2 catalogued extension." type CountScope { "Count these zones' bins (members belong to the count's LF; status-FREE — heal)." zoneIds: [ID!] "Count exactly these bins (members belong to the count's LF; status-FREE — heal)." binIds: [ID!] "Restrict the resolved IIs to ONE control class (non-controlled | lot-controlled | serially-controlled — the II attribute filter)." controlClass: String } "One resolved count line: a StockRecord shard (binId present, lotCode per the shard) or the derived un-binned POOL line (binId absent; whole-LF scope only). BLIND-BY-SHAPE: while the doc is counting, snapshotQty/expectedAtCapture/variance read null — the counter sees WHAT to count, never the expected; the full detail projects once the doc leaves counting (the store + archive always carry it)." type CountLine { "1-based position (resolution order at start) — the capture addressing key." lineNo: Int! "The counted InventoryItem (the (variant x LF) junction)." inventoryItemId: ID! "The record shard's bin — ABSENT = the un-binned POOL line." binId: ID "The record shard's lot (lot-controlled shards ride the records for free)." lotCode: String "The line's on_hand at START (the audit/blind baseline; NOT the variance base). Null while counting (blind-by-shape)." snapshotQty: String "The captured physical quantity (>= 0 — zeros are explicit captures; overwritable while counting). Null until captured." countedQty: String "The line's live on_hand POINT-READ at capture. Null while counting (blind-by-shape)." expectedAtCapture: String "When the capture landed (UTC ISO-8601; re-captures overwrite). Null until captured." capturedAt: String "DERIVED: countedQty − expectedAtCapture; null while counting and on uncaptured lines." variance: String } "A stock count: RECORDED stock vs PHYSICALLY-PRESENT stock at ONE LF, posting count_correct variance DELTAS (never absolute sets). Counts count ON_HAND presence only (condition rides reclass). posted is IMMUTABLE non-doomed history (recount = a NEW linked count); cancelled is the ONE doomed terminal (lists filter it). BLIND-BY-SHAPE while counting: line reads omit snapshot/expected/variance." type Count { id: ID! "The group-scoped human-facing system id (IC-…)." sysId: String! type: String! caption: String! "The FSM state: draft | counting | pending_review | posted | cancelled." status: String! "The parent counted LogicalFacility; for a Count parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The counted LF owning org (spine-derived at birth — the attribution precedent). IMMUTABLE." organizationId: ID! "The canned count type (physical | cycle | spot; DESCRIPTIVE.1). BIRTH-FIXED." countType: CountType! "The scope SELECTOR (BIRTH-FIXED verbatim; resolved ONCE at start; cancel + recreate to re-scope)." scope: CountScope! "The POSTED count this one re-counts." recountOfCountId: ID "The resolved lines. Captures mutate ONLY via captureCount under the doc OCC." lines: [CountLine!]! } "One page of the counts listing — the records + the opaque resume cursor." type CountPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Count!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for a Count. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). The LF, countType, scope and recount linkage are BIRTH-FIXED; lines/snapshots/captures mutate ONLY via start/capture under the doc OCC. A write while the doc rests in an immutable terminal (posted / cancelled) refuses CONFLICT/IMMUTABLE." input EditCountInput { caption: String } "A Contact's person block: a required name + optional title and reach lists (emails at most 8, phones at most 8)." type ContactPerson { name: String! title: String "RFC-shape email addresses, each at most 254 characters (non-empty when present, at most 8)." emails: [String!] "Free-shape bounded phone numbers (non-empty when present, at most 8)." phones: [String!] } "A Contact's inline address block: free-form lines (1..4) + the universally-present fields (the PostalAddress strictness stance)." type ContactAddress { lines: [String!]! city: String! "State / province / prefecture — optional (not universal across countries)." region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! } "A contact — the UNIFIED, REUSABLE contact-info master: one group-scoped record holding an optional PERSON block and/or an optional INLINE address block (at-least-one-of — an empty contact is refused at the boundary), attached to hosts via role-tagged ContactAssignments. Group-scoped like a Brand (parent = the org group). Carries EXTERNAL-party + functional addresses ONLY — the PhysicalFacilityLocation stays the SOLE physical-address holder for OUR facilities (the PFL fence). Deactivate AND doom are BOTH blocked by live (active) assignments." type Contact { id: ID! "The group-scoped human-facing system id (CO-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Contact parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The optional person block; absent on an address-only contact." person: ContactPerson "The optional inline address block; absent on a person-only contact." address: ContactAddress "Free-text notes (at most 4096 chars); absent when none." notes: String } "Person-block input for a Contact — a supplied block REPLACES the stored one WHOLESALE (no clearing semantic)." input ContactPersonInput { name: String! title: String emails: [String!] phones: [String!] } "Address-block input for a Contact — a supplied block REPLACES the stored one WHOLESALE." input ContactAddressInput { lines: [String!]! city: String! region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! } "Create-input for a Contact. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here. SUBSTANCE RULE (STRICT): at least one of person/address is REQUIRED — an empty contact is VALIDATION/INVALID." input NewContactInput { "Optional: when omitted the per-type default applies — the person's name when given, else 'Contact'; when supplied it must be non-blank." caption: String person: ContactPersonInput address: ContactAddressInput notes: String } "Edit-input for a Contact. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic): a supplied person/address block REPLACES the stored one WHOLESALE, so the birth substance rule can never be edited away. The FULL payload is mutable." input EditContactInput { caption: String "The replacement person block (wholesale)." person: ContactPersonInput "The replacement address block (wholesale)." address: ContactAddressInput notes: String } "The ContactAssignment HOST classes." enum ContactAssignmentHostType { organization_group organization logical_facility vendor corporate_customer } "A contact assignment — ONE role-tagged attachment of a Contact to a HOST construct (org group / organization / logical facility / vendor / corporate customer). Parent = the HOST (the CollectionMember stance — hostId rides the header parentId). The (contact, host, role) triple is unique (a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holder); REMOVE = doom (TWO_STATE — history preserved); re-assigning mints a NEW record via marker takeover. Role↔host applicability is registry DATA. At most 48 live assignments per host." type ContactAssignment { id: ID! "The group-scoped human-facing system id (CA-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent HOST construct; parentId === rootId only when the host IS the group." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The assigned Contact — set at creation, IMMUTABLE thereafter (a different link is a NEW assignment)." contactId: ID! "The host's construct class — the parent-slot discriminator; IMMUTABLE at birth." hostType: ContactAssignmentHostType! "The role this contact plays at the host — the canned + AT-extensible ContactRole registry (primary · owner · manager · billing-AP · accounts-receivable · purchasing-buyer · sales-rep · shipping-logistics · returns · support · technical · emergency); IMMUTABLE at birth." role: String! } "Create-input for a ContactAssignment. The tenant (org group) is derived SERVER-SIDE from the principal; hostId (the parent — rides the header) and contactId are tenant-scoped server-side and must BOTH be ACTIVE (STRICT); the resolved host must actually BE the named hostType; role↔host applicability is checked at the boundary (the ContactRole registry data)." input NewContactAssignmentInput { "Optional: when omitted the per-type default applies — the role's registry caption (e.g. 'Billing (AP)'); when supplied it must be non-blank." caption: String "The HOST construct id." hostId: ID! "The host's construct class — verified against the resolved host server-side." hostType: ContactAssignmentHostType! "The assigned Contact id — immutable after birth." contactId: ID! "The ContactRole token (canned registry — a non-canned or non-applicable role is VALIDATION/INVALID)." role: String! } "Edit-input for a ContactAssignment. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. Caption ONLY — every link field (contactId/hostType/role, and the host parent on the header) is IMMUTABLE at birth." input EditContactAssignmentInput { caption: String } "The canned warranty provider set." enum WarrantyProvider { manufacturer vendor } "Warranty terms — the WARRANTY POLICY TEMPLATE: provider + duration + coverage, attached to EXACTLY ONE of a Product or a Manufacturer (the manufacturer-attached row IS the reusable template). Group-scoped like a Brand (parent = the org group). The ATTACHMENT is the template's IDENTITY — IMMUTABLE at birth (re-attach = recreate); the POLICY payload stays mutable (the future warranty INSTANCE snapshots terms at sale, so a template edit never rewrites issued warranties). The warranty INSTANCE construct is NOT here." type WarrantyTerms { id: ID! "The group-scoped human-facing system id (WT-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a WarrantyTerms parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "WHO honors the warranty (the canned SPEC_REGISTRY set). Mutable." provider: WarrantyProvider! "The coverage duration in days from the (future) sale date (1..36500). Mutable." durationDays: Int! "Free-text coverage description (at most 8192 chars); absent when none. Mutable." coverage: String "The Product attachment leg (EXACTLY-ONE-OF with manufacturerId). IMMUTABLE at birth." productId: ID "The Manufacturer attachment leg (the reusable-template form). IMMUTABLE at birth." manufacturerId: ID } "Create-input for a WarrantyTerms. The tenant (org group) is derived SERVER-SIDE from the principal. ATTACHMENT RULE (STRICT): EXACTLY one of productId/manufacturerId — the target is tenant-scoped server-side and must be ACTIVE (CONFLICT/REF_STATE, the SL-b set-time gate)." input NewWarrantyTermsInput { "Optional: when omitted the per-type default applies — the policy coordinate ('Warranty d ()'); when supplied it must be non-blank." caption: String provider: WarrantyProvider! "The coverage duration in days (1..36500)." durationDays: Int! coverage: String "The Product attachment leg (exactly-one-of)." productId: ID "The Manufacturer attachment leg (exactly-one-of)." manufacturerId: ID } "Edit-input for a WarrantyTerms. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). The POLICY payload (provider/durationDays/coverage) is editable; the ATTACHMENT (productId/manufacturerId) is NOT (IMMUTABLE at birth — it is the template identity; re-attach = recreate)." input EditWarrantyTermsInput { caption: String provider: WarrantyProvider "The replacement duration in days (1..36500)." durationDays: Int coverage: String } "A Warranty — THE WARRANTY INSTANCE: one sold order line under one WarrantyTerms template. Born by the ENGINE when the sale completes (paid AND delivered) for every variant line whose product carries an active product-attached template or whose variant names a manufacturer carrying an active manufacturer-attached template (one warranty per matching template); never created on the wire. The policy is SNAPSHOTTED at birth (provider · durationDays → expiresAt = startsAt + durationDays), so later template edits never rewrite an issued warranty. `active → expired` is the scheduler’s over expiresAt; `active → claimed` is fileClaimWarranty (a warranty_claim CsCase linked both ways). The serial number is optional and stamped through updateWarranty. Listings keep expired warranties as coverage history (the settled-payment class — a status filter narrows to active); every warranty stays reachable by id from the order line’s warrantyIds." type Warranty { id: ID! "The group-scoped human-facing system id (WR-…)." sysId: String! type: String! caption: String! "The FSM state: active | claimed | expired." status: String! "The sold Order; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selling Organization (copied from the Order at birth)." organizationId: ID! "The sold line — the Order’s 1-based lineNo (frozen at placed; the cross-document addressing key)." orderLineNo: Int! "The sold Variant (the line’s variantId)." variantId: ID! "The Variant’s Product (resolved at birth)." productId: ID! "The WarrantyTerms template the warranty was issued under (a pointer — the policy is snapshotted on the record)." warrantyTermsId: ID! "WHO honors the warranty — snapshotted from the terms at birth (the claim’s routing)." provider: WarrantyProvider! "The coverage duration in days — snapshotted from the terms at birth." durationDays: Int! "The covered units — the line’s quantity at birth (the inventory decimal-string quantity shape)." quantity: String! "The coverage start — the sale’s completion instant (UTC ISO-8601)." startsAt: String! "The coverage end = startsAt + durationDays days (UTC ISO-8601); the scheduler sweeps active → expired on it." expiresAt: String! "The registered Consumer the order was for (from the Order’s customer capture, when present) — the customer-scoped listing axis." consumerId: ID "The unit’s serial number — optional; stamped through updateWarranty (at most 128 characters)." serialNumber: String "The warranty_claim CsCase the claim linked (stamped by fileClaimWarranty; present from claimed onward)." caseId: ID } "One page of the warranties listing — the records + the opaque resume cursor." type WarrantyPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Warranty!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for a Warranty. Every field optional, at least ONE required; supplied fields REPLACE The ONE edit is the serial-number stamp (typed at the counter or later; re-stampable — every value stays in the history); everything else is the engine’s snapshot or a transition stamp." input EditWarrantyInput { "The unit’s serial number (1..128 characters)." serialNumber: String! } "An org vendor item — the (OrgVendor × Variant) JUNCTION: this org buys THIS variant from THIS enabled vendor, carrying the vendor's part number / list cost / MOQ / lead time. Parent = the OrgVendor (the InventoryItem junction stance). The (orgVendor × variant) pair is unique (a live duplicate is CONFLICT/IDENTITY_TAKEN naming the holder; a doomed holder is taken over). OVIs are OPTIONAL by default. Live OVIs block the parent OrgVendor's doom AND the Variant's doom (CONFLICT/REFERENCED); OrgVendor deactivate stays free. Money reuses the MoneyEntry SDL (declared on the Product entry)." type OrgVendorItem { id: ID! "The group-scoped human-facing system id (EI-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent OrgVendor; for an OrgVendorItem parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The Variant leg of the junction — set at creation, IMMUTABLE thereafter (re-point = doom + create)." variantId: ID! "The VENDOR'S part number for this variant (their token, not our SKU; at most 128 chars); optional + editable." vendorPartNumber: String "The vendor's list cost — the currency must MATCH the parent OrgVendor's purchasingCurrency. The cost per PACK when purchasePackId is present; optional + editable." listCost: MoneyEntry "The minimum order quantity — STOCK-UoM units, or PACKS when purchasePackId is present; optional + editable." moq: Int "The per-item lead time in days (1..730) — OVERRIDES the OrgVendor default when present; optional + editable." leadTimeDays: Int "The vendor PurchasePack denomination for this junction. Must package THIS junction variant (tenant + ACTIVE + variant-coherence gated at every set); an edit supplying it while listCost/moq are stored re-supplies them in the SAME payload (the flip coupling); NO clearing semantic — un-denominating = doom + re-create. Optional + editable." purchasePackId: ID } "Create-input for an OrgVendorItem. The tenant (org group) is derived SERVER-SIDE from the principal; orgVendorId (the parent — rides the header) and variantId are tenant-scoped server-side and must BOTH be ACTIVE (STRICT); a supplied listCost requires the parent OrgVendor to carry a purchasingCurrency and must MATCH it." input NewOrgVendorItemInput { "Optional: when omitted the per-type default applies — the vendor's part number when given, else 'Org Vendor Item'; when supplied it must be non-blank." caption: String "The owning OrgVendor id." orgVendorId: ID! "The Variant this vendor supplies — immutable after birth." variantId: ID! vendorPartNumber: String "The vendor's list cost — the currency must match the parent OrgVendor's purchasingCurrency; the cost per PACK when purchasePackId is supplied." listCost: MoneyEntryInput moq: Int leadTimeDays: Int "The vendor PurchasePack denomination — tenant + ACTIVE + must package variantId." purchasePackId: ID } "Edit-input for a OrgVendorItem. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). variantId is NOT editable (IMMUTABLE junction identity — re-point = doom + create; the uniqueness marker never swaps), nor is the parent OrgVendor ref (the header). The commercial payload is editable; a supplied listCost re-gates against the parent purchasingCurrency; a supplied purchasePackId re-gates (tenant + ACTIVE + variant-coherence) AND requires stored listCost/moq re-supplied in the SAME payload (the denomination-flip coupling, lean 5)." input EditOrgVendorItemInput { caption: String vendorPartNumber: String "The replacement list cost (currency must match the parent purchasingCurrency; per PACK when the junction is pack-denominated)." listCost: MoneyEntryInput moq: Int leadTimeDays: Int "The replacement pack denomination — re-gated; stored listCost/moq must ride the same payload (the flip coupling)." purchasePackId: ID } "One embedded PurchaseOrder line." type PurchaseOrderLine { "1-based position (input order) — the receipt addressing key (poLineNo)." lineNo: Int! "The ordered variant (ACTIVE-gated; stockless service/bundle styles refuse — stock cannot be received into a stockless junction)." variantId: ID! "The RECEIVING LogicalFacility (must belong to the buying org) — defaulted from the OrgVendor defaultShipToLogicalFacilityId when omitted at create." logicalFacilityId: ID! "The ordered quantity (decimal string, stock UoM, strictly positive)." quantity: String! "The merchandise unit cost — REQUIRED effective; in the PO snapshot currency. The landed share joins at receipt post, NOT here." unitCost: MoneyEntry! "Optional per-line manufacturer." manufacturerId: ID "Optional expected-arrival instant (UTC ISO-8601) — defaulted create-date + (OVI?? OrgVendor) leadTimeDays when either declares one." expectedArrivalAt: String "Rollup: total received across POSTED receipts (stamped in the receipt-post transaction under the doc OCC)." receivedQty: String! "DERIVED: ordered minus received — never stored (the TR outstandingQty stance); the outstanding on partially_received IS the backorder." outstandingQty: String! "The pack-ENTRY audit capture: the pack whose IMMUTABLE unitsPerPack derived quantity (quantity == packQuantity x unitsPerPack, forever)." purchasePackId: ID "The entered pack count (present iff purchasePackId is)." packQuantity: Int "The special_order demand line this PO line backorders." orderLineRef: SpecialOrderLineRef } "The in-flight on-order walk of a large purchase order: present while status is issuing / cancelling / closing; the header IS the truth — the cursor and the chunk's stamps commit together, chunk by chunk, so a replayed step continues from the cursor." type PurchaseOrderWalk { "Which walk: issue (+ on order; from draft or pending_approval) · cancel (− on order; from issued) · close_short (− the open remainder; from partially_received)." kind: String! "The lineNo the NEXT chunk starts at — lines below it are stamped (cursor − 1 of lineCount landed)." cursor: Int! "Chunks committed so far (the inline first chunk counts)." chunks: Int! "The order's line count when the walk started — the progress denominator." lineCount: Int! "When the walk started (UTC ISO-8601)." startedAt: String! "No further notes." executionArn: String "Set when a step failed past its retries — the order is honestly stuck; re-run the same verb to resume." stalledAt: String "The stall cause (cut to 512 characters) — present with stalledAt." problem: String } "A purchase order: an org orders variants x quantities x receiving LFs from ONE enabled vendor (the OrgVendor enablement — IMMUTABLE at birth). Lines live in their OWN rows since and stay draft-editable wholesale (max 1000 — the NAMED assignment ceiling, raised from 48 with the rows; at most 90 line actions per CALL, so a big order grows through addPurchaseOrderLines; the same variant to N LFs = N lines,889); currency is the OrgVendor purchasingCurrency SNAPSHOT (every Money on the family matches it — NO FX, lean 5); received/closed_short are IMMUTABLE non-doomed history; cancelled is the ONE doomed terminal (lists filter it). Re-running the same verb RESUMES a stalled walk; on a healthy in-flight order it refuses CONFLICT/IN_PROGRESS naming the progress." type PurchaseOrder { id: ID! "The group-scoped human-facing system id (PO-…)." sysId: String! type: String! caption: String! "The FSM state: draft | pending_approval | issued | acknowledged | partially_received | issuing | cancelling | closing | received | closed_short | cancelled." status: String! "The parent BUYING Organization; for a PurchaseOrder parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The supplying OrgVendor enablement — IMMUTABLE at birth (re-vendor = cancel + new); ACTIVE-gated at create AND re-checked at issue." orgVendorId: ID! "The PO currency — a SNAPSHOT of the OrgVendor purchasingCurrency at create. Every Money on the family (line costs, landed components, invoice amounts, credits) must match it; the rate framework is the named FX trigger." currency: String! "Optional canned payment terms — snapshot defaulted from the OrgVendor at create, per-PO overridable." paymentTerms: String "Optional canned Incoterms 2020 rule (the registry, e.g. FOB / DDP) — snapshot defaulted from the OrgVendor at create, per-PO overridable." incotermCode: String "Optional vendor-side order/quote reference (their token — a bounded free string, max 64)." vendorReference: String "Optional free-text notes (max 4096)." notes: String "Rollup: the LIVE line rows on this order (0..1000) — maintained in the SAME transaction as every line mutation. ALWAYS <= nextLineNo - 1: removed numbers are never reused." lineCount: Int! "Rollup: the lines still OUTSTANDING (receivedQty < quantity). The system:all_received edge fires when this reaches 0 — O(1), never a line walk." openLineCount: Int! "The MONOTONIC next lineNo this order will assign (born 1; +1 per minted line; a removed number is NEVER reused, so the poLineNo addressing on Receipt + VendorInvoice stays unambiguous forever). Ceiling 1000 + 1 = the assignment exhausted." nextLineNo: Int! "Rollup: SIGMA (quantity x unitCost) over the live lines, in the PO snapshot currency — the vendor orderMinimum gate at issue reads THIS instead of summing lines. Landed components are NOT in it (they join at receipt post)." merchandiseTotal: MoneyEntry! "the ONE receipt mid-post against this order: set by a posting receipt’s first in-flight chunk, cleared by its last (the same transaction). A second receipt’s post refuses CONFLICT/IN_PROGRESS naming it, and close_short waits on it (policy:no_receipt_in_flight). Null when no receipt is walking." receivingReceiptId: ID "The WHOLE line set, read from the line ROWS in lineNo order and bounded by the 1000-line ceiling. To PAGE, FILTER or SORT them — or to read a big order without hydrating every line — use the purchaseOrderLines query. The receivedQty rollups mutate ONLY via receipt posts under the doc OCC." lines: [PurchaseOrderLine!]! "The IN-FLIGHT on-order walk: present EXACTLY while status is issuing / cancelling / closing — a large order whose stock stamps did not fit ONE transaction is written a chunk at a time, and this carries where it stands (kind · cursor = the next line to stamp, so cursor − 1 of lineCount landed · chunks so far · lineCount · startedAt · the machine executionArn once started · stalledAt + problem when a step failed past its retries). Null on every other status; cleared by the LAST chunk in the same transaction that lands the terminal. Re-run the same verb (issue / approve / cancel / close_short) to RESUME a stalled walk; on a healthy one it refuses CONFLICT/IN_PROGRESS naming the progress." walk: PurchaseOrderWalk } "One page of the purchaseOrders listing — the records + the opaque resume cursor." type PurchaseOrderPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PurchaseOrder!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One caller-supplied PurchaseOrder line (create + wholesale draft edit — lean 8: the receiving LF, unit cost and arrival are server-defaulted from the OrgVendor / OVI when omitted; a line whose LF or cost resolves to NOTHING refuses VALIDATION/INVALID naming the gap)." input PurchaseOrderLineInput { "The variant to order — tenant-scoped + ACTIVE; OVI-gated when the OrgVendor sets requireCatalogItem (a missing live OVI refuses NAMED)." variantId: ID! "The receiving LF — OPTIONAL (defaults from the OrgVendor defaultShipToLogicalFacilityId); must belong to the buying org." logicalFacilityId: ID "The ordered quantity (decimal string, strictly positive); below the OVI effective moq refuses NAMED. UNIT entry — exactly ONE of {quantity, the pack pair} per line." quantity: String "The merchandise unit cost — OPTIONAL (defaults from the OVI listCost; a pack-denominated OVI derives listCost / unitsPerPack, EXACT at 4 dp or the line refuses naming the cure — lean 7); REQUIRED effective after resolution; must match the PO snapshot currency." unitCost: MoneyEntryInput "Optional per-line manufacturer." manufacturerId: ID "Optional expected-arrival instant (UTC ISO-8601; defaults from lead time when either level declares one)." expectedArrivalAt: String "PACK entry: the pack to enter in — tenant + ACTIVE + must package THIS line variant; the stored quantity derives as packQuantity x unitsPerPack. Comes as a pair with packQuantity." purchasePackId: ID "The pack count (1..999999) — present iff purchasePackId is." packQuantity: Int "No further notes." orderLineRef: SpecialOrderLineRefInput } "Edit-input for a PurchaseOrder. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). DRAFT-ONLY WHOLESALE: header fields + a FULL line replace while draft (no per-line patching); the orgVendorId and the currency snapshot are BIRTH-FIXED (re-vendor = cancel + new); a live post-draft doc refuses CONFLICT/REF_STATE naming the required draft state (amend = cancel / close_short + a NEW PO); a write in an immutable terminal (received / closed_short / cancelled) refuses CONFLICT/IMMUTABLE." input EditPurchaseOrderInput { caption: String paymentTerms: String incotermCode: String vendorReference: String notes: String "The wholesale line replacement (draft-only) — same shape, defaults and gates as create; the WHOLE set, up to 1000.: it PERSISTS as a DIFF by the natural (variantId x logicalFacilityId) key — an unchanged line costs no write, a kept line KEEPS its lineNo, a new key mints at nextLineNo, an absent key deletes (a line carrying orderLineRef refuses CONFLICT/REFERENCED); a delta past 90 line actions refuses VALIDATION/INVALID naming the budget and the three line ops." lines: [PurchaseOrderLineInput!] } "The canned arrival dispositions." enum ReceiptDisposition { accept hold damage } "The canned landed-cost component types." enum LandedCostComponentType { freight customs_duty tariff insurance handling brokerage } "The allocation bases." enum LandedCostAllocationBasis { quantity value } "One landed-cost component (estimate at the Receipt; actual at the.3 VendorInvoice): a typed amount spread across the document's lines by its basis (allocateProportionally — exact conservation, remainder in line order)." type LandedCostComponent { "The canned component type." componentType: LandedCostComponentType! "The component amount — house Money in the PO snapshot currency." amount: MoneyEntry! "How the amount spreads across lines: quantity (per received unit) or value (per merchandise value)." basis: LandedCostAllocationBasis! } "One Receipt line." type ReceiptLine { "1-based, assigned at mint from the header nextLineNo — a removed number is never reused." lineNo: Int! "The PO line being received (1-based on the PARENT PO)." poLineNo: Int! "The quantity arriving NOW (strictly positive; cumulative across posted receipts <= ordered — over-receipt REFUSES at post)." quantityReceived: String! "The canned arrival routing." disposition: ReceiptDisposition! "The canned held reason — required iff disposition is hold (the law, strict both ways)." heldReason: String "Optional landing bin (binned receive stamps the StockRecord shard in the same transaction; omitted = the un-binned pool)." binId: ID "The pack-ENTRY audit capture: the pack whose IMMUTABLE unitsPerPack derived quantityReceived; may DIFFER from the PO line's pack." purchasePackId: ID "The entered pack count (present iff purchasePackId is)." packQuantity: Int "PORT-STAMPED at post (absent while draft): the merchandise unit cost — the PO line's unitCost at post (the merchandise half of the split; the audit +.3 true-up record)." merchandiseUnitCost: MoneyEntry "PORT-STAMPED at post (absent while draft): the effective LANDED unit cost (merchandise + the allocated estimate share per unit, half-up 4 dp — the display figure; the WMA re-weight uses the EXACT conserved value, never this re-rounded number)." landedUnitCost: MoneyEntry } "The in-flight post walk of a large receipt: present while status is posting; the header IS the truth — the cursor and the chunk's stock stamps commit together, chunk by chunk, so a replayed step continues from the cursor." type ReceiptWalk { "Which walk: post (the lines landing in stock; from draft)." kind: String! "The lineNo the NEXT chunk starts at — lines below it are booked (cursor − 1 of lineCount landed)." cursor: Int! "Chunks committed so far (the inline first chunk counts)." chunks: Int! "The receipt's line count when the walk started — the progress denominator." lineCount: Int! "When the walk started (UTC ISO-8601)." startedAt: String! "No further notes." executionArn: String "Set when a step failed past its retries — the receipt is honestly stuck; re-run post to resume." stalledAt: String "The stall cause (cut to 512 characters) — present with stalledAt." problem: String } "Over-receipt refuses CONFLICT/THREE_WAY_MATCH (the PO declared receive.match_flag form; tolerance ZERO until); under-receipt is partial, first-class — the next receipt is a NEW doc. posted is the immutable NON-doomed fact (corrections are compensating movements, never edits); cancelled is the doomed terminal (lists filter it). Re-running post RESUMES a stalled walk; on a healthy in-flight receipt it refuses CONFLICT/IN_PROGRESS naming the progress; one receipt posts against a purchase order at a time (its receivingReceiptId)." type Receipt { id: ID! "The group-scoped human-facing system id (RC-…)." sysId: String! type: String! caption: String! "The FSM state: draft | posting | posted | cancelled." status: String! "The parent PurchaseOrder (SPEC_CATALOG: PO per-LF — the saga this doc advances; receipts enumerate via the generic parent-children walk); for a Receipt parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The receiving LogicalFacility — IMMUTABLE at birth (the Transfer LF-pair stance; wrong LF = cancel + recreate); must be named by >=1 parent-PO line; ACTIVE-re-checked at post (the SL-b use-time stance)." logicalFacilityId: ID! "The buying org — spine-stamped from the parent PO at birth (the attribution symmetry)." organizationId: ID! "Rollup: the LIVE line rows on this receipt (0..1000) — maintained in the SAME transaction as every line mutation. ALWAYS <= nextLineNo - 1: removed numbers are never reused." lineCount: Int! "The MONOTONIC next lineNo this receipt will assign (born 1; +1 per minted line; a removed number is NEVER reused). Ceiling 1000 + 1 = the assignment exhausted." nextLineNo: Int! "The lines — child rows (RCPTLINE#) read LAZILY as a whole (<= 1000, in lineNo order; the 12-line embedded ceiling and its 7N+2 transaction bound retired: the post WALKS). Page them with receiptLines; edit wholesale (the diff rule) or through addReceiptLines · updateReceiptLine · removeReceiptLines while draft. Fixed at post — the chunk that books a line stamps its merchandiseUnitCost / landedUnitCost on the row." lines: [ReceiptLine!]! "The landed-cost ESTIMATE components — allocated into the receive unit cost at post via allocateProportionally (EXACT conservation); trued up at VI capture." landedComponents: [LandedCostComponent!] "The post walk in flight: present EXACTLY while status is posting — kind post · cursor = the next lineNo to land in stock (cursor − 1 of lineCount landed) · chunks so far · lineCount · startedAt · the machine executionArn once started · stalledAt + problem when a step failed past its retries. Null on every other status; cleared by the LAST chunk in the same transaction that lands posted. Re-run post to RESUME a stalled walk; on a healthy one it refuses CONFLICT/IN_PROGRESS naming the progress." walk: ReceiptWalk } "One page of the receipts listing — the records + the opaque resume cursor." type ReceiptPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Receipt!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One caller-supplied Receipt line (create · wholesale draft edit · the line ops — lineNo assigned from the header nextLineNo by the kit, never reused)." input ReceiptLineInput { "The PO line being received (1-based on the PARENT PO; must name a line destined to this receipt's LF)." poLineNo: Int! "The quantity arriving NOW (decimal string, strictly positive). UNIT entry — exactly ONE of {quantityReceived, the pack pair} per line." quantityReceived: String "The canned arrival routing (accept / hold / damage)." disposition: ReceiptDisposition! "The canned held reason — required iff disposition is hold (strict both ways)." heldReason: String "Optional landing bin." binId: ID "PACK entry: the pack the arrival is counted in — tenant + ACTIVE + must package the ADDRESSED PO line's variant; quantityReceived derives as packQuantity x unitsPerPack. Comes as a pair with packQuantity." purchasePackId: ID "The pack count (1..999999) — present iff purchasePackId is." packQuantity: Int } "One caller-supplied landed-cost ESTIMATE component." input LandedCostComponentInput { componentType: LandedCostComponentType! amount: MoneyEntryInput! basis: LandedCostAllocationBasis! } "Edit-input for a Receipt. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet; the ONE exception: an EMPTY landedComponents array CLEARS the estimates). DRAFT-ONLY WHOLESALE (the family stance): caption + a FULL line replace + a FULL component replace while draft; the parent PO and the LF are BIRTH-FIXED (wrong LF = cancel + recreate — the Transfer pair precedent); a live post-draft doc refuses CONFLICT/REF_STATE naming the required draft state; a write in an immutable terminal (posted / cancelled) refuses CONFLICT/IMMUTABLE." input EditReceiptInput { caption: String "The wholesale line replacement (draft-only) — same shape and gates as create; the WHOLE set, up to 1000.: it PERSISTS as a DIFF by the natural (poLineNo x disposition) key — an unchanged line costs no write, a kept line KEEPS its lineNo and createdAt, a new key mints at nextLineNo, an absent key deletes; a delta past 90 line actions refuses VALIDATION/INVALID naming the budget and the three line ops." lines: [ReceiptLineInput!] "The wholesale component replacement (draft-only); an EMPTY array clears the estimates." landedComponents: [LandedCostComponentInput!] } "The canned RTV return reasons: defective / wrong_item typically cite a PO; overstock / recall are the PO-less class." enum RtvReason { defective overstock recall wrong_item } "One embedded Rtv line." type RtvLine { "1-based position (input order at create)." lineNo: Int! "The variant being returned." variantId: ID! "The (variant x ship-from LF) InventoryItem junction — server-resolved + STAMPED at create (TR-f; must EXIST + be active)." inventoryItemId: ID! "The quantity to return (decimal string, stock UoM, strictly positive)." quantity: String! "The canned return reason." reason: RtvReason! "The bucket this line ships FROM (on_hand / damaged / held — the -mutable trio; reserved / in_transit are never RTV-shippable)." sourceBucket: StockBucket! "Optional source bin (binned relief stamps the StockRecord shard in the same transaction; omitted = the un-binned pool)." binId: ID } "A return-to-vendor: goods ship BACK to an enabled vendor for credit. Parent = the OrgVendor. Lifecycle: draft compose (wholesale edits) - approve (authority:approve_rtv, a REAL maker/checker step from birth) - ship fires the FIRST rtv movements (sourceBucket relief at CURRENT WMA, lean 6 — the sell/ symmetry; present stock only, CONFLICT/INSUFFICIENT_STOCK else; resolvedReturnsContactId + the expectedCredit default stamp here) - record_credit closes it (actual!= expected refuses CONFLICT/CREDIT_MISMATCH retryable; acknowledgeVariance is the explicit cure — the variance stays reports-only, no AR/AP). Lines are EMBEDDED (max 24 — the 3N+1<=100 ship ceiling held, -m), each shipping from on_hand / damaged / held (the -mutable trio); cancel is pre-ship ONLY; credited is the immutable NON-doomed close; cancelled is the ONE doomed terminal (lists filter it)." type Rtv { id: ID! "The group-scoped human-facing system id (RV-…)." sysId: String! type: String! caption: String! "The FSM state: draft | approved | shipped | credited | cancelled." status: String! "The parent OrgVendor enablement; for an Rtv parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The returning org — spine-stamped from the parent OrgVendor at birth (the attribution symmetry)." organizationId: ID! "The OPTIONAL originating PurchaseOrder (defective/wrong-item returns cite their PO; overstock/recall may not). Must belong to the SAME OrgVendor and be past-issue when named." purchaseOrderId: ID "The LF the return ships FROM — IMMUTABLE at birth (the Transfer pair stance); SL-b: ACTIVE-gated at create, re-checked at ship." shipFromLogicalFacilityId: ID! "Optional expected vendor credit (in the vendor purchasingCurrency) — when absent, ship stamps the default: the sum of line quantity x CURRENT WMA over the relieved books." expectedCredit: MoneyEntry "The credit the vendor actually issued — STAMPED by record_credit (absent until credited)." actualCredit: MoneyEntry "TRUE when a mismatched credit was explicitly acknowledged at record_credit." creditVarianceAcknowledged: Boolean "The resolved returns-destination Contact — STAMPED at ship (the OrgVendor returnsToContactId?? the vendor host single live returns-role assignment; neither resolvable refuses NAMED)." resolvedReturnsContactId: ID "The EMBEDDED lines (1..24 — the NAMED ceiling, -m; distinct variant x sourceBucket x bin keys) — draft-editable wholesale; junctions server-resolved + STAMPED at create (TR-f: the (variant x ship-from LF) InventoryItem must EXIST)." lines: [RtvLine!]! } "One page of the rtvs listing — the records + the opaque resume cursor." type RtvPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Rtv!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One caller-supplied Rtv line (create + wholesale draft edit — lineNo assigned and the junction resolved 1..N in input order by the server)." input RtvLineInput { "The variant to return — its (variant x ship-from LF) junction must EXIST and be active (IV-b; an RTV of a variant never stocked at the LF is meaningless)." variantId: ID! "The quantity to return (decimal string, strictly positive)." quantity: String! "The canned return reason." reason: RtvReason! "The bucket to ship from — OPTIONAL, defaults to on_hand; on_hand / damaged / held only (reserved / in_transit refuse at the boundary)." sourceBucket: StockBucket "Optional source bin." binId: ID } "Edit-input for a Rtv. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). DRAFT-ONLY WHOLESALE (the family stance): caption + expectedCredit + a FULL line replace while draft; the OrgVendor, the PO ref, and the ship-from LF are BIRTH-FIXED (re-point = cancel + recreate — the Transfer pair precedent); a live post-draft doc refuses CONFLICT/REF_STATE naming the required draft state; a write in an immutable terminal (credited / cancelled) refuses CONFLICT/IMMUTABLE." input EditRtvInput { caption: String "The expected vendor credit replacement (draft-only; in the vendor purchasingCurrency)." expectedCredit: MoneyEntryInput "The wholesale line replacement (draft-only) — same shape, resolution and gates as create; lineNo reassigned 1..N in input order." lines: [RtvLineInput!] } "The capture-stamped match outcome." enum VendorInvoiceMatchStatus { matched flagged } "The capture-time match axes." enum VendorInvoiceMatchAxis { quantity unit_cost } "One capture-STAMPED match discrepancy (port-written at capture; the expected/actual values are decimal/Money-amount strings stored verbatim)." type VendorInvoiceMatchFlag { "The PO line the discrepancy is on." poLineNo: Int! "The axis that missed." axis: VendorInvoiceMatchAxis! "The PO-side value." expected: String! "The invoiced value." actual: String! } "One embedded merchandise match line." type VendorInvoiceMatchLine { "1-based position (input order)." lineNo: Int! "The PO line this invoice line bills (1-based on the PARENT PO)." poLineNo: Int! "The invoiced quantity (strictly positive)." quantity: String! "The invoiced unit cost — house Money in the PO currency." unitCost: MoneyEntry! } "A captured vendor bill: the 3-way match and the landed-cost TRUE-UP run from it at capture. NOT a payables subledger. Parent = the PO (the match is per-PO; N invoices per PO are legal — partial-shipment invoicing); invoiceOrgVendorId MAY differ from the PO vendor: ONE construct covers merchandise invoices (match lines) AND cost bills (landed ACTUAL components) — either or both, never neither. CAPTURE stamps matchStatus matched|flagged at tolerance ZERO (price/qty variance FLAGS, never blocks — the flag IS the approval queue until) and posts the landed true-up (actuals vs the receipts NOT-yet-trued estimates per component type -> cost_true_up value-only movements re-weighting each touched book at its CURRENT cost-bearing quantity; the sold-share stays a reports-only fact — the precedent). The (invoiceOrgVendor x normalized invoice number) UNIQ pair is the double-pay gate (CONFLICT/IDENTITY_TAKEN naming the holder; a cancelled holder is taken over). captured is the immutable fact (corrections are compensating entries, never un-capture); cancelled is the doomed terminal (lists filter it)." type VendorInvoice { id: ID! "The group-scoped human-facing system id (VI-…)." sysId: String! type: String! caption: String! "The FSM state: draft | captured | cancelled." status: String! "The parent PurchaseOrder; for a VendorInvoice parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The BILLING OrgVendor — may differ from the PO vendor (a carrier/broker billing against this PO); defaults to the PO vendor at create. IMMUTABLE at birth (the marker leg)." invoiceOrgVendorId: ID! "The vendor own invoice number (their token, RAW spelling, max 64; the trim+case-fold normalized leg rides the UNIQ pair marker — the double-pay gate). IMMUTABLE at birth." invoiceNumber: String! "The vendor invoice date (UTC ISO-8601 — their paper date, not our capture instant)." invoiceDate: String! "The merchandise match lines (<=24, one per PO line) — at-least-one-of with actualComponents (the Contact substance stance)." matchLines: [VendorInvoiceMatchLine!] "The landed-cost ACTUAL components (<=8, amounts in the PO currency) — trued-up at capture against the posted receipts estimates of the SAME component type (first capture of a type consumes its estimates; later bills of that type add compensating deltas)." actualComponents: [LandedCostComponent!] "Optional vendor-stated grand total (informational — the lines/components are the match facts); in the PO currency." total: MoneyEntry "Optional free-text notes (max 4096)." notes: String "CAPTURE-stamped match outcome (absent while draft): flagged never blocked the capture — it IS the approval queue until." matchStatus: VendorInvoiceMatchStatus "CAPTURE-stamped discrepancies (first-8 named; port-written, never caller data)." matchFlags: [VendorInvoiceMatchFlag!] } "One page of the vendorInvoices listing — the records + the opaque resume cursor." type VendorInvoicePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [VendorInvoice!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One caller-supplied match line (create + wholesale draft edit — lineNo assigned 1..N in input order by the kit)." input VendorInvoiceMatchLineInput { "The PO line this invoice line bills (must exist on the parent PO)." poLineNo: Int! "The invoiced quantity (decimal string, strictly positive)." quantity: String! "The invoiced unit cost — house Money in the PO currency." unitCost: MoneyEntryInput! } "Edit-input for a VendorInvoice. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. DRAFT-ONLY WHOLESALE: date/lines/components/total/notes + caption while draft; the PO parent, the billing vendor, and the invoice number are BIRTH-FIXED (the marker identity — re-key = cancel + recreate, the marker takeover covers the same number); a write in an immutable terminal (captured / cancelled) refuses CONFLICT/IMMUTABLE." input EditVendorInvoiceInput { caption: String invoiceDate: String "The wholesale match-line replacement (draft-only); an EMPTY array clears the merchandise lines — substance re-checked against the effective components." matchLines: [VendorInvoiceMatchLineInput!] "The wholesale component replacement (draft-only); an EMPTY array clears the cost bill — substance re-checked against the effective match lines." actualComponents: [LandedCostComponentInput!] total: MoneyEntryInput notes: String } "A purchase pack — a purchasing/handling packaging definition ON a variant (case of 24, pallet of 480): NOT a UoM conversion (the inventory ledger is ALWAYS in the variant stock UoM — reaffirmed); a pack is packaging metadata + a line-ENTRY breakdown step (PO/Receipt lines entered in packs resolve to stock units at entry: packQuantity x unitsPerPack). Parent = the VARIANT (0..N packs per variant). unitsPerPack is IMMUTABLE at birth, which keeps every stored document line reconstructible forever. The code is a dup-gated LABEL (trim+case-fold vs LIVE siblings on the same variant, naming the holder — lean 1: no UNIQ marker). Live packs block the parent Variant doom (the children law); live OrgVendorItems naming a pack block ITS doom; deactivate stays FREE everywhere (an inactive pack refuses NEW line entry while its unitsPerPack keeps denominating stored terms)." type PurchasePack { id: ID! "The group-scoped human-facing system id (PK-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Variant; for a PurchasePack parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The pack label (at most 64 chars) — dup-gated among LIVE siblings on the same variant; editable (re-gated)." code: String! "Stock units per pack in the variant stock UoM (strictly positive decimal, 4 dp — covers weight-UoM variants). IMMUTABLE at birth." unitsPerPack: String! "Optional pack GTIN — GTIN-14/ITF-14 validated (14 digits + check digit, helpers; a PLAIN field — the org-scoped identifier LEDGER stays variant-only, lean 3); optional + editable." packGtin: String "Optional nominal pack weight in KILOGRAMS (fixed unit — lean 4); optional + editable." nominalWeightKg: String "Optional outer length in CENTIMETERS (the dims trio — all three or none, lean 4); optional + editable." lengthCm: String "Optional outer width in CENTIMETERS (the dims trio); optional + editable." widthCm: String "Optional outer height in CENTIMETERS (the dims trio); optional + editable." heightCm: String } "Create-input for a PurchasePack. The tenant (org group) is derived SERVER-SIDE from the principal; variantId (the parent — rides the header) is tenant-scoped server-side and must be ACTIVE (STRICT); the code is dup-gated against LIVE sibling packs (trim+case-fold, naming the holder); the dims trio comes all-or-none." input NewPurchasePackInput { "Optional: when omitted the per-type default applies — the pack code; when supplied it must be non-blank." caption: String "The variant this pack packages." variantId: ID! code: String! "Stock units per pack (strictly positive decimal) — IMMUTABLE after birth." unitsPerPack: String! packGtin: String nominalWeightKg: String lengthCm: String widthCm: String heightCm: String } "Edit-input for a PurchasePack. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). unitsPerPack is NOT editable (IMMUTABLE at birth, lean 2 — the pack essence; a different count = doom + create), nor is the parent Variant ref (the header). A supplied code re-runs the sibling dup-gate; every edit re-gates the parent Variant ACTIVE (the OVI parent-enablement stance); the dims trio comes all-or-none." input EditPurchasePackInput { caption: String "The replacement label — re-runs the sibling dup-gate (naming a LIVE holder refuses)." code: String packGtin: String nominalWeightKg: String lengthCm: String widthCm: String heightCm: String } "The canned ABC classes." enum AbcClass { A B C } "The buy-vs-transfer-and-backfill thresholds — ONE sparse parameter block; a supplied block sets at least one threshold." type ReplenishmentBuyVsTransfer { "Projected-stockout horizon (days) that makes a deficit URGENT (velocity-dependent)." urgencyHorizonDays: Int "The farthest donor considered for an urgent transfer (km — the LF-PF-PFL geodistance chain)." maxTransferDistanceKm: Int "A donor must hold at least this much GENUINE excess before it donates (stock units)." minDonorExcessUnits: String } "A replenishment config — ONE cell of the multi-axis planning parameter matrix: a set of AXES naming a scope (absent = all — the sparse matrix; Location = organizationId XOR logicalFacilityId · Merchandise = categoryId XOR styleId · seasonId · brandId, each SINGULAR) + a SPARSE block of parameters (at least one — the substance rule). Group-scoped like a Brand (parent = the org group). The AXES are the cell identity — IMMUTABLE at birth (re-target = create + doom); parameter VALUES stay editable (nothing clears — removing a parameter = doom + create). the collision rule: an ACTIVE sibling with the SAME normalized axis tuple AND an intersecting SET-parameter set refuses CONFLICT/IDENTITY_TAKEN naming the holder + the intersecting parameters (same-tuple DISJOINT-parameter cells are legal — per-parameter semantics; an inactive cell neither resolves nor collides, so REACTIVATE re-runs the gate). Specificity (the.2 per-parameter resolution): count of set axes, then the locked axis order Location > Merchandise > Season > Brand. A NON-doomed cell blocks its axis targets dooms (LF/Organization/Category/Style/Season/Brand); deactivate stays FREE." type ReplenishmentConfig { id: ID! "The group-scoped human-facing system id (RP-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a ReplenishmentConfig parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The Location axis, org level (XOR logicalFacilityId; absent = group-wide). IMMUTABLE at birth." organizationId: ID "The Location axis, LF level (XOR organizationId). IMMUTABLE at birth." logicalFacilityId: ID "The Merchandise axis, category level (XOR styleId; matches the subtree). IMMUTABLE at birth." categoryId: ID "The Merchandise axis, style level (XOR categoryId; outranks ANY category depth). IMMUTABLE at birth." styleId: ID "The Season axis (absent = all seasons). IMMUTABLE at birth." seasonId: ID "The Brand axis (absent = all brands). IMMUTABLE at birth." brandId: ID "The master switch for the.2 replenishment suggester over this scope. Editable." replenishEnabled: Boolean "The band floor (stock units, the 12-digit/4-dp quantity grammar); minUnits must not exceed maxUnits. Editable." minUnits: String "The band ceiling (stock units). Editable." maxUnits: String "Velocity-consuming days-of-supply target (1..3650 — the velocity boundary is disclosed in provenance, -i). Editable." daysOfSupplyTarget: Int "FIXED safety stock (stock units) — a service-level METHOD is the named registry-extensible successor. Editable." safetyStockUnits: String "The FORCE reorder-multiple override (stock units, strictly positive) — DEFAULT = the pack/MOQ derivation. Editable." reorderMultipleUnits: String "Review cadence (1..3650) — a PARAMETER consumed by derived reads; nothing fires by itself. Editable." reviewCadenceDays: Int "Pin this scope to an ABC class regardless of the computed cut lines. Editable." abcClassOverride: AbcClass "The buy-vs-transfer-and-backfill thresholds. Editable." buyVsTransfer: ReplenishmentBuyVsTransfer "Stock a donor NEVER gives up (stock units) — the genuine-excess floor. Editable." reserveFloorUnits: String "May this scope DONATE excess at all. Editable." transferableExcess: Boolean "The fair-share weight for the.2 allocation suggester (1..10000). Editable." allocationWeight: Int } "The buyVsTransfer input twin — at least one threshold when supplied." input ReplenishmentBuyVsTransferInput { urgencyHorizonDays: Int maxTransferDistanceKm: Int minDonorExcessUnits: String } "Create-input for a ReplenishmentConfig. The tenant (org group) is derived SERVER-SIDE from the principal. AXES (STRICT): each SINGULAR (at most one Location leg, at most one Merchandise leg), every supplied ref tenant-scoped server-side + ACTIVE (CONFLICT/REF_STATE); at least ONE parameter (the substance rule); minUnits must not exceed maxUnits; the write-time COLLISION gate runs BEFORE the write." input NewReplenishmentConfigInput { "Optional: when omitted the per-type default applies — the set-axis coordinate ('Replenishment ()'; 'Replenishment (group-wide)' when none); when supplied it must be non-blank." caption: String "The Location axis, org level (at most one Location leg)." organizationId: ID "The Location axis, LF level (at most one Location leg)." logicalFacilityId: ID "The Merchandise axis, category level (at most one Merchandise leg)." categoryId: ID "The Merchandise axis, style level (at most one Merchandise leg)." styleId: ID seasonId: ID brandId: ID replenishEnabled: Boolean minUnits: String maxUnits: String daysOfSupplyTarget: Int safetyStockUnits: String reorderMultipleUnits: String reviewCadenceDays: Int abcClassOverride: AbcClass buyVsTransfer: ReplenishmentBuyVsTransferInput reserveFloorUnits: String transferableExcess: Boolean allocationWeight: Int } "Edit-input for a ReplenishmentConfig. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic: removing a parameter = doom + create)." input EditReplenishmentConfigInput { caption: String replenishEnabled: Boolean minUnits: String maxUnits: String daysOfSupplyTarget: Int safetyStockUnits: String reorderMultipleUnits: String reviewCadenceDays: Int abcClassOverride: AbcClass buyVsTransfer: ReplenishmentBuyVsTransferInput reserveFloorUnits: String transferableExcess: Boolean allocationWeight: Int } "The canned TransferLane modes. ⚠ INACTIVE lane = ABSENT, not never — a standing prohibition must stay ACTIVE never." enum TransferLaneMode { never always ranked } "The canned TransferLane weight classes — light out-ranks shipped at equal distance." enum TransferLaneWeightClass { light shipped } "A transfer lane — ONE DIRECTED source→destination LF pair the operator has declared: never (a standing prohibition), always (the preferred donor class), or ranked (an explicit ordering). Group-scoped like a Brand (parent = the org group). THE MATRIX IS SPARSE + the geo seed is VIRTUAL: an ABSENT pair ranks by geodistance (LF→PF→PFL.geo) AT READ — no seeder materializes derivable rows; overriding the default = creating the specific lane. The PAIR is IMMUTABLE at birth (re-route = create + doom; src == dest refused) and UNIQUE per group (the ordered-pair marker — a LIVE duplicate is CONFLICT/IDENTITY_TAKEN naming the holder; a doomed holder is taken over). rank is REQUIRED iff mode is ranked and REFUSED otherwise (strict both ways; a mode moving OFF ranked DROPS the stored rank — the merged-record law). ⚠ INACTIVE = ABSENT, not never: deactivating returns the pair to the sparse geodistance default — a standing prohibition must stay ACTIVE never. A NON-doomed lane blocks BOTH its LFs dooms; deactivate stays FREE. Money reuses the MoneyEntry SDL (declared on the Product entry)." type TransferLane { id: ID! "The group-scoped human-facing system id (TL-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a TransferLane parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The DONOR LF of this directed lane. IMMUTABLE at birth (the pair is the lane identity + its uniqueness marker)." sourceLfId: ID! "The RECEIVING LF of this directed lane. IMMUTABLE at birth." destinationLfId: ID! "The lane mode (never | always | ranked — the canned SPEC_REGISTRY set). Editable (the merged rank ⊕ mode law re-runs)." mode: TransferLaneMode! "The explicit ordering (1..10000, lower first) — REQUIRED iff mode is ranked, REFUSED otherwise (strict both ways)." rank: Int "Optional typical lane transit time in days (1..730; informational + engine provenance). Editable." typicalLeadTimeDays: Int "Optional weight class — light out-ranks shipped at equal distance. Editable." weightClass: TransferLaneWeightClass "Optional per-transfer cost hint — house Money, NO currency gate (the.2 buy-vs-transfer compare consumes it ONLY currency-matched, -g). Editable." costHint: MoneyEntry } "Create-input for a TransferLane. The tenant (org group) is derived SERVER-SIDE from the principal; sourceLfId and destinationLfId are tenant-scoped server-side, must BOTH be ACTIVE (CONFLICT/REF_STATE), and must DIFFER; rank is REQUIRED iff mode is ranked (strict both ways); the ordered-pair marker reserves in the SAME transaction (a LIVE holder refuses CONFLICT/IDENTITY_TAKEN naming it; a DOOMED holder is taken over)." input NewTransferLaneInput { "Optional: when omitted the per-type default applies — the mode coordinate ('Transfer lane ()'); when supplied it must be non-blank." caption: String "The donor LF (the directed pair is immutable after birth)." sourceLfId: ID! "The receiving LF (must differ from sourceLfId)." destinationLfId: ID! mode: TransferLaneMode! "REQUIRED iff mode is ranked, REFUSED otherwise." rank: Int typicalLeadTimeDays: Int weightClass: TransferLaneWeightClass costHint: MoneyEntryInput } "Edit-input for a TransferLane. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). The PAIR (sourceLfId/destinationLfId) is NOT editable (IMMUTABLE at birth — the lane identity AND its uniqueness marker; re-route = create + doom, lean). mode/rank edit under the MERGED-record rank ⊕ mode law: merged mode ranked requires a rank (stored or supplied); merged mode NOT ranked DROPS the stored rank and REFUSES a supplied one." input EditTransferLaneInput { caption: String mode: TransferLaneMode "The replacement ordering — legal only when the MERGED mode is ranked." rank: Int typicalLeadTimeDays: Int weightClass: TransferLaneWeightClass costHint: MoneyEntryInput } "The jurisdiction levels (generated from the contracts TAX_JURISDICTION_LEVELS SoT — anti-drift; the declaration ORDER is the depth rank). Canned — extensible by the platform, never merchant-defined." enum TaxJurisdictionLevel { country state_province county city special_district } "The tax regimes (generated from the contracts TAX_REGIMES SoT): sales_tax rates STACK across the nested chain; vat_gst is a single (usually inclusive) rate. HST = a combined-rate row (the TaxRate combined flag); GST+PST = two stacked rows." enum TaxRegime { sales_tax vat_gst } "A tax jurisdiction — ONE node of OUR canonical jurisdiction tree (roots = countries; full local depth for the US). SHARED-CANONICAL, ruled: AT builds and maintains this data centrally; merchants REFERENCE it (TaxRegistration nexus, ExemptionCertificate scopes, the calc) and never edit it — the wire is READ-ONLY (writes are kit-channel: the US+CA seed slice). The tree is the MUTABLE treeParent pointer; regime/countryCode/currencyCode ride the COUNTRY root only (descendants inherit by walk-up)." type TaxJurisdiction { id: ID! "The GLOBAL-namespace human-facing system id (TJ-…, account-wide, like the Account's)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "No further notes." parentId: ID "The shared-canonical listing ANCHOR — the country root's id (a root self-roots: rootId === id) / the owning jurisdiction; NEVER an org group." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The depth class — a child sits STRICTLY deeper than its tree parent (skips legal: cities under states). IMMUTABLE." level: TaxJurisdictionLevel! "The MUTABLE tree pointer — absent ⟺ a country root. Moves stay in-country." treeParent: ID "COUNTRY ROOTS ONLY: sales_tax (rates STACK down the chain) | vat_gst (single rate). Descendants inherit by walk-up." regime: TaxRegime "COUNTRY ROOTS ONLY: ISO 3166-1 alpha-2 (uppercase) — also the one-live-tree-per-country GLOBAL uniqueness marker value." countryCode: String "COUNTRY ROOTS ONLY: ISO 4217 (uppercase) — the currency TaxRate thresholds are minor units of." currencyCode: String "Optional official geography code (ISO 3166-2 region / FIPS county / place code …) — seed-pipeline provenance; NOT an identity key." code: String } "One page of the taxJurisdictions listing — the records + the opaque resume cursor." type TaxJurisdictionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TaxJurisdiction!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The jurisdiction×category rule outcomes (generated from the contracts TAX_TREATMENTS SoT): taxable | reduced | zero_rated | exempt — zero_rated and exempt both price at 0 (the distinction is real: zero-rated supplies keep input credits) and may be threshold-conditional." enum TaxTreatment { taxable reduced zero_rated exempt } "A tax rate cell — ONE effective-dated (jurisdiction × category × window) cell of OUR canonical rate tables, carrying BOTH the rule outcome (treatment) AND the rate (integer parts-per-million — 6.625% = 66250). SHARED-CANONICAL + READ-ONLY on the wire (the ruling rides down from the tree; writes are kit-channel — the seed slice). A DATED_SCHEDULE: half-open [startAt, endAt) windows, splice-normalized PER (jurisdiction × category) sub-schedule — the record set IS the full rate history; supersede, never rewrite. exempt/zero_rated cells price at 0 (zero_rated keeps input credits — the distinction feeds remittance). compound = tax-on-tax; combined = the HST marker (this rate REPLACES the ancestor stack). An optional threshold scopes the rule to unit prices STRICTLY BELOW it (minor units of the country currency — the BC childrens-clothing shape)." type TaxRate { id: ID! "The GLOBAL-namespace human-facing system id (TX-…, account-wide, like the Account's)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The owning TaxJurisdiction; for a TaxRate parentId === rootId (the shared-canonical anchor, T-c) — always present." parentId: ID! "The shared-canonical listing ANCHOR — the country root's id (a root self-roots: rootId === id) / the owning jurisdiction; NEVER an org group." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The taxed category. One sub-schedule per (jurisdiction × category). IMMUTABLE." category: TaxCategory! "The rule outcome. IMMUTABLE — supersede to change." treatment: TaxTreatment! "The rate in integer parts-per-million (0..1000000; 6.625% = 66250). 0 ⟺ zero_rated/exempt. IMMUTABLE." ratePpm: Int! "Tax-on-tax: applies over the base PLUS prior stacked tax. IMMUTABLE." compound: Boolean! "The HST marker: this rate REPLACES the ancestor-chain stack. IMMUTABLE." combined: Boolean! "Optional: the rule applies to unit prices STRICTLY BELOW this (minor units of the jurisdiction country currency); at-or-above falls through to the node standard-category cell. IMMUTABLE." thresholdMinorUnits: Int "The window start (inclusive; UTC ISO-8601). IMMUTABLE." startAt: String! "The window end (EXCLUSIVE; UTC ISO-8601; always present — far-future = the standing rate). Moves ONLY via the system splice trim." endAt: String! } "One page of the taxRates listing — the records + the opaque resume cursor." type TaxRatePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TaxRate!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "A tax registration — the org's NEXUS declaration for ONE jurisdiction: tax computes ONLY where the org holds an ACTIVE registration (the calc gate). The OPERATIONAL semantics: active = the org collects there · inactive = a lapsed/suspended registration (resumable) · doomed = deregistered. ONE live registration per (org × jurisdiction) — the pair marker; the PAIR is IMMUTABLE at birth (re-register = create + doom). jurisdictionId refs the SHARED canonical tree. Physical-nexus seeding from PFLs and economic-nexus tracking are spec-deferred." type TaxRegistration { id: ID! "The group-scoped human-facing system id (TN-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The registering Organization; for a TaxRegistration parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The registered TaxJurisdiction. IMMUTABLE at birth (the pair is the identity + its uniqueness marker)." jurisdictionId: ID! "Optional permit/registration number issued by the jurisdiction. Editable (corrections are real)." registrationNumber: String "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the taxRegistrations listing — the records + the opaque resume cursor." type TaxRegistrationPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TaxRegistration!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a TaxRegistration. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent — rides the header) is tenant-scoped server-side and must be ACTIVE; jurisdictionId is a SHARED-canonical ref — it must EXIST and be ACTIVE (CONFLICT/REF_STATE naming it) but is deliberately NOT tenant-scoped (shared data is the point); the (org × jurisdiction) pair marker reserves in the SAME transaction (a LIVE holder refuses CONFLICT/IDENTITY_TAKEN naming it; a DOOMED holder is taken over)." input NewTaxRegistrationInput { "Optional: when omitted the per-type default applies — the jurisdiction coordinate ('Registration: '); when supplied it must be non-blank." caption: String "The registering Organization (the containment parent) — tenant-scoped + ACTIVE." organizationId: ID! "The registered TaxJurisdiction (shared-canonical: exists + ACTIVE; NOT tenant-scoped). The pair is immutable after birth." jurisdictionId: ID! registrationNumber: String code: String } "Edit-input for a TaxRegistration. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). The PAIR (organizationId/jurisdictionId) is NOT editable (IMMUTABLE at birth — the identity AND its uniqueness marker; re-register = create + doom, T-h)." input EditTaxRegistrationInput { caption: String "The corrected permit number (corrections are real)." registrationNumber: String code: String } "The exemption-certificate kinds." enum ExemptionCertType { resale nonprofit government diplomatic other } "A tax-exemption certificate — a captured legal document: a valid in-scope cert ZEROES tax at sale for its covered jurisdictions/categories (the calc consumes it; at-USE validity = status active ∧ not past expiresAt ∧ scope match — CONFLICT/EXPIRED per SPEC_ERRORS). Parent = the org group, FIXED AT BIRTH (the / customer host is a later REF, never a reparent). Capture is INLINE. The capture is IMMUTABLE except caption/code/docRef — correct anything else by revoking and re-capturing. active → expired is SCHEDULED; revoke and doom are the caller ops." type ExemptionCertificate { id: ID! "The group-scoped human-facing system id (XC-…)." sysId: String! type: String! caption: String! "The FSM state: active | expired | revoked | doomed." status: String! "The parent org group; for an ExemptionCertificate parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The certificate kind. IMMUTABLE at capture." certType: ExemptionCertType! "The issuer's certificate number. IMMUTABLE at capture." certificateNumber: String! "The holder as captured INLINE. IMMUTABLE at capture." holderName: String! "The covered jurisdictions — SHARED-canonical refs, each exists+ACTIVE at capture. IMMUTABLE." jurisdictionIds: [ID!]! "The covered categories — ABSENT = all categories (the blanket-cert shape). IMMUTABLE." categoryIds: [TaxCategory!] "Optional expiry (UTC ISO-8601) — ABSENT = non-expiring. The scheduler arms active→expired on it; the at-USE check is the calc's. IMMUTABLE." expiresAt: String "Optional document reference (a blob pointer/URI — upload machinery is NOT this slice). Editable (the paper gets scanned later)." docRef: String "The holder linkage: the OrgCustomer this cert belongs to. Set-time gated (in-tenant, NON-doomed); EDITABLE — re-linkable (the ONE exception to capture immutability; the capture-doc parent stays the GROUP). A NON-doomed cert blocks its holder's doom." orgCustomerId: ID "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the exemptionCertificates listing — the records + the opaque resume cursor." type ExemptionCertificatePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ExemptionCertificate!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input to CAPTURE an ExemptionCertificate. The tenant (org group) is derived SERVER-SIDE from the principal; every scoped jurisdiction is a SHARED-canonical ref — each must EXIST and be ACTIVE (CONFLICT/REF_STATE naming the first non-live one), deliberately NOT tenant-scoped; categories validate against the canned TaxCategory registry; the capture is immutable except caption/code/docRef — correct by revoke + re-capture." input NewExemptionCertificateInput { "Optional: when omitted the per-type default applies — the capture coordinate (' cert — '); when supplied it must be non-blank." caption: String certType: ExemptionCertType! "The issuer's certificate number (non-blank; STRICT)." certificateNumber: String! "The certificate holder, captured inline (customer-linked)." holderName: String! "The covered jurisdictions (1..25; shared-canonical refs — each exists + ACTIVE)." jurisdictionIds: [ID!]! "The covered categories — ABSENT = all (the blanket-cert shape); supplied lists are non-empty." categoryIds: [TaxCategory!] "Optional expiry (UTC ISO-8601) — ABSENT = non-expiring." expiresAt: String docRef: String "The holder OrgCustomer — in-tenant + NON-doomed at set." orgCustomerId: ID code: String } "Edit-input for a ExemptionCertificate. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). A captured legal document is otherwise IMMUTABLE: certType/certificateNumber/holderName/jurisdictionIds/categoryIds/expiresAt are NOT editable — correct by revoking and re-capturing. orgCustomerId is the ONE ref exception." input EditExemptionCertificateInput { caption: String "The document reference (the paper gets scanned/re-referenced later)." docRef: String "The holder OrgCustomer — re-linkable; in-tenant + NON-doomed at set." orgCustomerId: ID code: String } "The Order selling channels." enum OrderChannel { pos ecom } "The orderType birth discriminator (generated from ORDER_TYPE_VALUES — anti-drift)." enum OrderType { sale draft quote layaway special_order } "The special_order per-line sourcing paths (generated from ORDER_LINE_SOURCING_TYPES — anti-drift): transfer links a TransferRequest line · backorder links a PurchaseOrder line · buyer_request is the DECLARED-DORMANT arm." enum OrderLineSourcingType { transfer backorder buyer_request } "The special_order demand-line address a sourcing doc line carries." type SpecialOrderLineRef { "The special_order Order." orderId: ID! "The 1-based order line." orderLineNo: Int! } "No further notes." input SpecialOrderLineRefInput { "The special_order Order id (tenant-scoped)." orderId: ID! "The 1-based order line to source." orderLineNo: Int! } "The per-line fulfillment methods." enum OrderFulfillmentMethod { carryout ship pickup_curbside pickup_instore deliver_later special_order } "The discount sources in the FIXED application order (generated from SALE_DISCOUNT_SOURCES — anti-drift). manual is the ONLY caller-suppliable source — coupon/promo entries are ENGINE-EMITTED server-side; loyalty/employee arrive /e." enum SaleDiscountSource { manual coupon promo loyalty employee } "A discount entry kind — an absolute minor-unit amount or an integer-ppm percentage (10% = 100000)." enum SaleDiscountKind { amount percent } "How a line tax figure came to be: computed = the pipeline ran; nexus_none = no ACTIVE registration on the origin chain (zero tax is the CORRECT outcome); exempt = a valid ExemptionCertificate applied." enum OrderTaxBasis { computed nexus_none exempt } "The inline customer capture — at least one inline field OR the corporate ref." type OrderCustomer { name: String email: String phone: String "The captured CorporateCustomer." corporateCustomerId: ID "The purchasing-buyer Contact on THAT customer's host." buyerContactId: ID "The captured Consumer." consumerId: ID } "The document-level ship-to destination: ONE address shape for the Order AND the Fulfillment's ship stamp; complete by construction (a partial address is never stored)." type OrderShipTo { name: String! "The street address (1..3 lines)." addressLines: [String!]! city: String! region: String postalCode: String "ISO 3166-1 alpha-2, uppercase." countryCode: String! phone: String } "The SELECTED fulfillment option snapshot: the rate card / pickup choice as picked; method ∈ ORDER_FULFILLMENT_OPTION_METHODS (the agent channel's offer vocabulary)." type OrderFulfillmentOption { method: String! "The channel's option id the platform echoed (a shipping card slug · pickup_instore · pickup_curbside)." optionId: String! caption: String! "The fee in the order currency's minor units (0 = free shipping · every pickup)." feeMinor: Int! handlingDays: Int minDays: Int maxDays: Int "The pickup location (one of the channel's pickup LogicalFacilities) — pickup methods only." pickupLogicalFacilityId: ID } "The agent checkout's buyer names as the platform gave them (beside the customer block's joined name)." type OrderAgentCheckoutBuyer { firstName: String lastName: String } "The platform-captured consent decisions — a purpose present = asserted; absent = the channel default speaks." type OrderAgentCheckoutConsent { marketing: Boolean analytics: Boolean preferences: Boolean sale_or_sharing: Boolean } "THE AGENT CHECKOUT BLOCK: present ⟺ this Order is a UCP checkout session." type OrderAgentCheckout { agentChannelId: ID! "The platform that opened it (its UCP profile URL) — absent on a staff test drive." platformProfileUrl: String "The platform's own shipping-destination id, echoed on the checkout." shipToId: String buyer: OrderAgentCheckoutBuyer consent: OrderAgentCheckoutConsent "THE PENDING SALE MARK: the sale this checkout's complete minted before the card hold settled; present ⟺ a completion is in flight (the checkout reads complete_in_progress)." pendingSaleId: ID "THE INSTRUMENT the platform submitted at complete: its instrument id · the handler id · the type — on the MINTED sale only; never a credential." instrument: OrderAgentCheckoutInstrument } "The platform's instrument as submitted at complete: ids and type only — the processor truth (brand · last four) lives on the Payment." type OrderAgentCheckoutInstrument { id: String! handlerId: String! type: String! } "One pre-tax discount — amount XOR percent per kind; the audit reason is REQUIRED. Engine emissions (source coupon/promo) carry their ref and an engine-stamped reason; they are ABSOLUTE amount entries computed to replay verbatim in the pipeline." type OrderDiscount { kind: SaleDiscountKind! source: SaleDiscountSource! "The absolute reduction in minor units (present ⟺ kind amount)." amountMinor: Int "The percentage in integer ppm (present ⟺ kind percent)." percentPpm: Int reason: String! "The emitting Promotion — present ⟺ source promo (engine-stamped, NEVER caller input)." promotionId: ID "The carrying Coupon — present ⟺ source coupon (engine-stamped; NEVER caller input)." couponId: ID "The redeeming LoyaltyMember — present ⟺ source loyalty (engine-stamped, NEVER caller input)." loyaltyMemberId: ID "The verified employee User — present ⟺ source employee (engine-stamped, NEVER caller input)." employeeUserId: ID } "The loyalty attach. redeemPoints ABSENT = attach-for-EARN-only; PRESENT = the redemption request the position-4 evaluation converts to source=loyalty LINE entries (pre-tax — the / taxonomy law: loyalty is a DISCOUNT, never a tender). SALE-profile only; re-validated on EVERY engine run and at PLACE (commit truth)." type OrderLoyalty { "The attached LoyaltyMember — tenant/program/currency-gated at the seam." memberId: ID! "The redemption request in points (≤ the member balance — CONFLICT/INSUFFICIENT_POINTS names live figures)." redeemPoints: Int } "The employee-discount attach. The position-5 evaluation converts it to source=employee LINE entries (the LAST pre-tax reduction); the percent is caller-supplied v1 under the LIVE discount.apply authority gate. EVERY orderType may carry it (the coupon posture); the User re-validates FRESH at PLACE." type OrderEmployee { "The verified employee User." userId: ID! "The discount percent in integer ppm ((0, 1000000] — the SaleDiscount grammar; 20% = 200000)." percentPpm: Int! } "One commission-attribution slot." type OrderCommissionAgent { agentUserId: ID! splitWeightPpm: Int! } "The open_item non-catalog payload — no variant, no stock movement; category explicit." type OrderOpenItem { description: String! taxCategory: TaxCategory! } "The stored_value entry payload: selling/reloading a StoredValueInstrument AS a line (proceeds = a LIABILITY; NO stock movement, NOT engine-matched, tax basis instrument_sale — the untaxed-issuance law; the explicit taxCategory stays INERT until a jurisdiction override). Arms resolve at PLACE (commit truth): instrumentId ABSENT ⇒ the place MINTS (born active + issue; the consumed code drops from the stored line); PRESENT + staged inactive ⇒ ACTIVATES + issues; PRESENT + active reloadable gift_card ⇒ RELOADS (CONFLICT/NOT_RELOADABLE otherwise). store_credit lines refuse (never purchasable); sale-profile only; quantity ≡ 1; carryout only; never discounted." type OrderStoredValue { instrumentType: StoredValueInstrumentType! "The targeted/minted instrument — PLACE stamps it on the mint arm." instrumentId: ID "The NORMALIZED merchant-issued code on a PRE-place mint line (consumed + dropped when the place stamps instrumentId)." code: String "The EXPLICIT tax category (the open_item law) — inert under basis instrument_sale until." taxCategory: TaxCategory! } "One computed tax component captured on the line." type OrderLineTaxComponent { taxRateId: ID! jurisdictionId: ID! "The GOVERNING cell category — discloses whether the line category ruled or the standard fallback did." category: TaxCategory! treatment: TaxTreatment! ratePpm: Int! compound: Boolean! combined: Boolean! taxMinor: Int! } "The line tax slot — basis DISCLOSED." type OrderLineTax { basis: OrderTaxBasis! taxMinor: Int! components: [OrderLineTaxComponent!]! "Present ⟺ basis exempt — the applied ExemptionCertificate (arms the doom guard)." exemptCertificateId: ID } "One embedded Order line — lineNo frozen at placed; money audit server-stamped per write." type OrderLine { "1-based input position — the cross-document addressing key once placed." lineNo: Int! "The sold variant (the 3-way entry-mode XOR with openItem / storedValue)." variantId: ID "The resolved (variant × LF) InventoryItem — present ⟺ variantId (price capture + reserve junction)." inventoryItemId: ID "The SalePrice record whose window governed the capture — present ⟺ variantId (audit provenance)." salePriceId: ID openItem: OrderOpenItem "The stored-value payload." storedValue: OrderStoredValue "The resolved tax category — the variant→product→style walk answer, or the open-item/stored-value explicit one." taxCategory: TaxCategory! "Positive decimal-string quantity (the stock-UoM grammar; open items unit-counted)." quantity: String! "The captured unit sale price in minor units." capturedUnitPriceMinor: Int! discounts: [OrderDiscount!]! fulfillmentMethod: OrderFulfillmentMethod! nonReturnable: Boolean finalSale: Boolean restockingFeePpm: Int requiresApprovalToSell: Boolean commissionAgents: [OrderCommissionAgent!] referralCode: String "The LIVE reservation claim stamped by the ecom place — the release entries + the terminal status are the history." reservedQty: String "The cumulative INVOICED quantity: stamped by issueInvoice / un-stamped by voidInvoice under this doc's OCC; the un-invoiced remainder = quantity − invoicedQty (absent = 0)." invoicedQty: String "The cumulative RETURNED quantity: stamped by receiveReturn under this doc's OCC; the returnable remainder = quantity − returnedQty (absent = 0)." returnedQty: String "The cumulative FULFILLMENT-CLAIMED quantity: Σ open + delivered Fulfillment claims, stamped by createFulfillment / un-stamped by cancelFulfillment under this doc's OCC; the unclaimed remainder = quantity − fulfillmentClaimedQty (absent = 0). Carryout lines claim at the paid-completion delivery." fulfillmentClaimedQty: String "The cumulative DELIVERED quantity: stamped by the delivery lanes (ship/handover/the carryout paid-completion) under this doc's OCC; both delivery vectors aggregate it (absent = 0)." fulfilledQty: String "The cumulative RELIEVED quantity: stamped by the sell-relief lane in ITS transaction (absent = 0)." relievedQty: String "The Warranties born on this line at the sale's completion: engine-stamped in the birth transaction under this doc's OCC (the idempotency mark — a re-run births nothing twice); ABSENT until the birth; never caller-typed. Ref-only — THE ORDER-SIDE LINK; each warranty's parentId is this order and its orderLineNo this line." warrantyIds: [ID!] "The sourcing path this special_order line rides." sourcingType: OrderLineSourcingType "The linked sourcing document (transfer → the TransferRequest; backorder → the PurchaseOrder) — re-stamped only when the linked doc is DEAD (the re-link retry lane)." sourcingDocId: ID "The 1-based line on THAT doc (the TR-b per-line shape mirrored)." sourcingDocLineNo: Int "The cumulative ARRIVED quantity: stamped by the arrival follow-ups (receiveTransfer / the Receipt post) in their per-order transactions; on_hand landings ONLY; the line is arrived when arrivedQty ≥ quantity (absent = 0)." arrivedQty: String "The per-unit COGS snapshot at relief." cogsUnitCost: MoneyEntry "Step-1 base = round(quantity × capturedUnitPriceMinor), half away from zero." baseMinor: Int! "Σ applied line discounts (step 2)." lineDiscountMinor: Int! "This line largest-remainder share of the order-level discounts (exact — no lost minor units)." orderDiscountShareMinor: Int! "base − line discounts − order share (floored at zero) — the taxable base." taxableBaseMinor: Int! "taxableBase + exclusive-regime tax; pre-place = taxableBase." lineTotalMinor: Int! "The tax slot — pipeline-written at place; absent while the cart is open/held." tax: OrderLineTax } "The canned tender types (SPEC_REGISTRY row 92 VERBATIM, generated from the contracts TENDER_TYPES SoT — anti-drift; + the amendment). cash + external_card + foreign_cash + card are LIVE; the others refuse VALIDATION/UNSUPPORTED naming their arrival (gift/store-credit → · on_account →); merchant CUSTOM tenders = a named deferral." enum TenderType { cash card gift_card gift_certificate store_credit on_account foreign_cash external_card } "The external_card capture — a card authorized on a THIRD-PARTY pinpad (Worldpay/etc.), recorded by entering the result; NO Stripe Payment, NO processor call." type TenderExternalCard { "The card brand/type (Visa/MC/…) — required." brand: String! "Optional last four digits." last4: String "Optional device/terminal reference." deviceRef: String "The auth/approval number — required." authNumber: String! } "The foreign-cash capture: the FOREIGN side of the conversion (physical cash collected, in ITS currency) + the exact COMPOSED buy rate applied; the row-level figures stay settlement-currency." type TenderFx { "The tendered FOREIGN currency." currency: String! "The physical FOREIGN cash handed over, in its minor units (before change — the drawer's per-currency holding)." collectedMinor: Int! "The WINNING FxRate record consumed." rateId: ID! "The COMPOSED effective BUY rate applied, integer micro to-per-from." rateMicro: Int! "The accumulated adjustment fee withheld from the credit, settlement-currency minor units." feeMinor: Int } "ONE applied tender: FSM-LESS by ratified intent (SPEC_CATALOG / — status is always active; the lifecycle is its Payment / the money facts); sysId-LESS (the class); IMMUTABLE — reversal = a NEW refund tender row (negative appliedMinor), never an edit. Posted ONLY by applyTender, refundTender, and the refund writers (refundReturn/posReturn method=cash) — each in ONE transaction with the Order rollup stamp (+ the drawer entries for cash)." type Tender { id: ID! type: String! "The derived display caption — tenderType + currency + signed applied minor; never editable." caption: String! "FSM-less: always active." status: String! "The parent Order." parentId: ID! rootId: ID! "The canned tender type (SPEC_REGISTRY row 92)." tenderType: TenderType! "SIGNED minor units APPLIED toward the order balance — positive = payment, negative = a refund tender." appliedMinor: Int! "The settlement currency — the order currency snapshot." currency: String! "CASH, positive tenders: the PHYSICAL cash handed over (before change, tip included)." collectedMinor: Int "CASH: the physical change handed back (the change_given drawer lane)." changeMinor: Int "The tip captured at tender." tipMinor: Int "The cash-rounding ledger note (settling cash tenders): roundedDue − exactDue — the sale total NEVER changes." roundingDeltaMinor: Int "The pinpad capture (external_card tenders only)." externalCard: TenderExternalCard "The foreign-cash capture (foreign_cash tenders only)." fx: TenderFx "The Payment this card tender was spawned by (card tenders only; the payment read tells the processor story)." paymentId: ID "The StoredValueInstrument this tender drew from or credited." instrumentId: ID "The OrgCustomer house account this tender charged or credited." orgCustomerId: ID "The Return this refund tender settles." returnId: ID "The drawer session a cash tender settled to/paid out of." tillSessionId: ID "The caller's reason (required on refund tenders)." reason: String "Provenance document refs (bounded free strings)." refs: [String!] createdAt: String! updatedAt: String! revision: ID! revisionNum: Int! } "A selling Order — the cart IS the open state (no Cart construct); orderType selects the FSM profile; lines embed with captured prices in integer minor units; the tax slots are pipeline-written at place over the master data; ecom place reserves stock, POS place does not — a layaway place reserves BOTH channels for the term; a special_order place NEVER reserves (goods are not on-hand — arrival reserves the claim)." type Order { id: ID! "The group-scoped human-facing system id (SO-…)." sysId: String! type: String! caption: String! "The FSM state: open | held | placed | completed | voided | abandoned | cancelled | draft | sent | accepted | expired | accruing | paid_in_full | defaulted | sourcing | ready. The orderType profile selects the instance's FSM — states beyond its profile are unreachable for it." status: String! "pos → the selling LogicalFacility; ecom → the Organization — fixed at birth by origin, never reparented; rootId = the org group either way." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selling Organization — IMMUTABLE at birth; ACTIVE-gated at create." organizationId: ID! "The selling channel — IMMUTABLE; decides the parent + the reserve arm." channel: OrderChannel! "The birth discriminator — IMMUTABLE; selects the FSM profile. ALL FOUR profiles buildable: sale + draft/quote + layaway + special_order." orderType: OrderType! "The draft/quote validity window end — REQUIRED on quote, OPTIONAL on draft, absent elsewhere; accept past it refuses CONFLICT/EXPIRED (the at-USE gate); once set the scheduler strand fires the draft|sent → expired rows on schedule." validUntil: String "The layaway TERM end: the instant the scheduler fires placed|accruing → defaulted (claims released; deposits stay recorded — settlement is the operator's follow-up). OPTIONAL (absent ⇒ no scheduled default), layaway-only, FUTURE-dated, editable while live (a termEndsAt-ONLY edit stays legal at placed|accruing — the term is schedule, not content)." termEndsAt: String "The conversion ref — the placed sale Order this draft/quote MINTED at accept; accepted-state only." convertedOrderId: ID "The conversion back-ref — the draft/quote this sale was converted FROM (stamped at the mint birth); sale-profile only." sourceDocumentId: ID "The reorder provenance ref — the sale-profile source Order this order was reordered FROM (stamped SERVER-SIDE by reorderOrder at the clone birth, never caller-writable; prices re-captured FRESH at the mint, never copied); sale-profile only. Distinct from sourceDocumentId: conversion CONSUMES its doc, a reorder consumes nothing." reorderOfOrderId: ID "The selling/fulfilling LF — pricing capture + the ecom reserve ride its InventoryItems (per-line sourcing =)." logicalFacilityId: ID! "The order currency — the org defaultCurrency snapshot, FIXED at create." currency: String! "Optional inline customer capture." customer: OrderCustomer "The document-level ship-to destination: stamped by the agent checkout when a COMPLETE shipping address arrives (the Fulfillment's shipTo at ship is the same shape); absent otherwise." shipTo: OrderShipTo "The SELECTED fulfillment option snapshot + its fee: the channel's rate card or pickup choice as picked (words · fee in minor units · transit days · the pickup location); the fee is a SEPARATE quote line — the accept adds it to the sale." fulfillmentOption: OrderFulfillmentOption "THE AGENT CHECKOUT BLOCK: present ⟺ this Order is a UCP checkout session — the AgentChannel · the platform profile URL (absent on a staff test drive) · the platform's destination id · the buyer names as given · the captured consent decisions." agentCheckout: OrderAgentCheckout "Optional ExemptionCertificate ref — at-USE validity gated at place." exemptionCertificateId: ID "Order-level pre-tax discounts — allocated to lines pro-rata by discounted subtotal, largest remainder (exact)." discounts: [OrderDiscount!]! "The payment rollup — stamped from net tendered vs total at every tender post." paymentState: String! "The fulfillment rollup — born unfulfilled; transitioned by the events." fulfillmentState: String! "The recognition rollup — born deferred (deposits-until-delivery); conversion = the delivery events." recognitionState: String! "The ORIGIN jurisdiction captured at place; absent pre-place or when the PFL is unclassified (the disclosed nexus-none arm)." taxJurisdictionId: ID "Σ line bases in minor units." subtotalMinor: Int! "Everything taken off pre-tax (line discounts + the order-level reduction), minor units." discountTotalMinor: Int! "Σ line tax in minor units — 0 until place; INSIDE the captured prices under an inclusive (vat_gst) regime (disclosed, not double-counted)." taxTotalMinor: Int! "The order total in minor units — exclusive regimes add tax; inclusive regimes carry it inside the captured prices." totalMinor: Int! "The fulfillment fee folded into the money at COMMIT: the agent checkout's selected option fee restated as a money rollup on the MINTED sale (totalMinor = Σ line totals + this + its tax); absent on drafts and on every non-agent sale." fulfillmentFeeMinor: Int "The tax on the fulfillment fee (taxed as a standard good at the origin — the lean), INSIDE taxTotalMinor; present ⟺ fulfillmentFeeMinor." fulfillmentFeeTaxMinor: Int "Σ signed applied minor over the order tenders; absent = no tender yet. balance due = totalMinor − this." tenderedNetMinor: Int "Σ tips captured at tender; absent = none." tipTotalMinor: Int "The Payment attempts spawned by card tenders (append-at-mint, the bounded by-order path; ≤ 32 doubles as the attempts cap; declined attempts keep their slot); absent = none." paymentIds: [ID!] "The Refund attempts spawned by refundReturn(original_tender) (append-at-mint, the paymentIds law; ≤ 64 doubles as the attempts cap; failed attempts keep their slot, audit truth); absent = none." refundIds: [ID!] "The Disputes webhook-born against this order’s payments (append-at-mint, ≤ 32; terminal disputes keep their slot); absent = none." disputeIds: [ID!] "The Invoices issued from this order. The bounded order→invoice enumeration the settlement/recognition attribution reads; absent = none." invoiceIds: [ID!] "The Coupons ATTACHED to this order. A trigger coupon's promotion evaluates ONLY while attached; PLACE re-validates every member and refuses a non-applied one. Absent = none." couponIds: [ID!] "The loyalty attach. Earn commits at PLACE on the FINAL post-ALL-step-2-reductions discounted taxable base (position 5 included; storedValue lines excluded); the redemption emits source=loyalty LINE entries at position 4. SALE-profile only; absent = none." loyalty: OrderLoyalty "The employee-discount attach. The position-5 evaluation emits source=employee LINE entries (the LAST pre-tax reduction); EVERY orderType may carry it (the coupon posture — a pure reduction mints nothing); the User re-validates FRESH at PLACE. Absent = none." employee: OrderEmployee "The special_order_sourcing Saga stamped at launch; special_order-profile only." sourcingSagaId: ID "The commission custody stamp: the DISTINCT union of attributed agents + manager-on-all holders whose entries minted — the deterministic clawback walk-list (the resolvedInventoryItemIds custody class)." commissionAgentUserIds: [ID!] "The affiliate custody stamp: the attributed Affiliate — the clawback walk key (entries ride AFFLEDGER#)." affiliateId: ID "The embedded lines (0..45 — an empty open cart is legal, place refuses it); lineNo frozen at placed." lines: [OrderLine!]! } "One page of the orders listing — the records + the opaque resume cursor." type OrderPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Order!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The inline customer capture — at least one inline field OR a customer ref." input OrderCustomerInput { name: String email: String phone: String "The CorporateCustomer REF — resolves in-tenant; the (order-org × cc) OrgCustomer must exist and be ACTIVE (CONFLICT/REF_STATE names the missing/paused enablement)." corporateCustomerId: ID "The buyer Contact — requires corporateCustomerId; must hold a LIVE purchasing-buyer assignment on THAT customer's host (role-EXACT)." buyerContactId: ID "The Consumer REF: resolves in-tenant + ACTIVE (a suspended/erased consumer refuses CONFLICT/REF_STATE); MUTUALLY EXCLUSIVE with corporateCustomerId; PLACE/accept re-validate FRESH; the consumer's priceGroupId SUPERSEDES the member carrier at pricing." consumerId: ID } "One pre-tax discount entry — amountMinor ⟺ kind amount, percentPpm ⟺ kind percent; reason REQUIRED. Only source manual is accepted from CALLERS (VALIDATION/INVALID otherwise — the input boundary refuses every other source; the coupon/promo/loyalty/employee engines emit their entries server-side, the gate stands FOREVER — the wording rule: the live wire answers INVALID, never UNSUPPORTED). Engine refs (promotionId/couponId) are OUTPUT-only — never accepted here." input OrderDiscountInput { kind: SaleDiscountKind! source: SaleDiscountSource! amountMinor: Int percentPpm: Int reason: String! } input OrderCommissionAgentInput { agentUserId: ID! splitWeightPpm: Int! } "The open_item entry payload — description + explicit tax category + explicit unit price (house Money; the currency MUST match the order currency)." input OrderOpenItemInput { description: String! taxCategory: TaxCategory! unitPrice: MoneyEntryInput! } "The stored_value entry payload: the instrument type/target + the EXPLICIT tax category + the LOAD amount as the unit price (house Money; the currency MUST match the order currency — cross-currency issuance is the deferral). instrumentId names an EXISTING instrument (staged-activate / reload); code rides the MINT arm only (normalized + grammar-gated at add; omitted = system-minted at place). store_credit refuses (never purchasable); quantity ≡ 1; never discounted; carryout only; sale-profile only (the slice-2 amendment)." input OrderStoredValueInput { instrumentType: StoredValueInstrumentType! instrumentId: ID code: String taxCategory: TaxCategory! unitPrice: MoneyEntryInput! } "One caller line — variantId XOR openItem XOR storedValue; variant lines price from the (variant × LF) schedule at add-time (a lapsed/unpriced item refuses CONFLICT/REF_STATE); quantity strictly positive." input OrderLineInput { variantId: ID openItem: OrderOpenItemInput storedValue: OrderStoredValueInput quantity: String! discounts: [OrderDiscountInput!] "Omitted ⇒ channel default (pos → carryout, ecom → ship)." fulfillmentMethod: OrderFulfillmentMethod nonReturnable: Boolean finalSale: Boolean restockingFeePpm: Int requiresApprovalToSell: Boolean commissionAgents: [OrderCommissionAgentInput!] referralCode: String } "Create-input to open an Order — a sale/layaway/special_order is born open (the cart IS the open state); a draft/quote is born draft. The org + LF are gated live (ACTIVE, same group, the LF belongs to the org); the currency snapshots the org defaultCurrency (UNSET refuses VALIDATION/INVALID naming it; outside the registry refuses VALIDATION/UNSUPPORTED_CURRENCY); lines MAY be empty (the ecom cart-birth shape). ALL FOUR orderType profiles are accepted; a special_order line is VARIANT-keyed with fulfillmentMethod=special_order (defaulted; an explicit other method or an openItem refuses — the coupling). validUntil is REQUIRED on quote (FUTURE instant), OPTIONAL on draft, forbidden elsewhere." input NewOrderInput { "Optional: when omitted the per-type default applies — the channel + line count (pos order 2 lines); when supplied it must be non-blank." caption: String "The selling Organization — tenant-scoped + ACTIVE." organizationId: ID! channel: OrderChannel! "ALL FOUR profiles accepted; special_order lines are variant-keyed + method-coupled." orderType: OrderType! "The draft/quote validity window end — REQUIRED iff quote, OPTIONAL on draft, forbidden elsewhere; must be FUTURE at create." validUntil: String "The layaway term end: OPTIONAL on layaway (absent ⇒ no scheduled default), forbidden elsewhere; must be FUTURE at create." termEndsAt: String "The selling/fulfilling LF — ACTIVE + belongs to the selling org." logicalFacilityId: ID! customer: OrderCustomerInput "Optional cert ref — same-group + active at attach; at-USE validity re-gated at place." exemptionCertificateId: ID "Order-level pre-tax discounts (manual only)." discounts: [OrderDiscountInput!] "The lines (0..45)." lines: [OrderLineInput!]! } "Edit-input for a Order. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). LIVE-EDIT-STATE ONLY: a sale edits while open (held is parked — resume first; post-place content is frozen, the amendment window a strict-OFF hook); a draft/quote edits while draft OR sent. A supplied lines array REPLACES wholesale and re-runs the FULL price capture at the edit instant." input EditOrderInput { caption: String customer: OrderCustomerInput exemptionCertificateId: ID discounts: [OrderDiscountInput!] "Re-set the draft/quote validity window." validUntil: String "Re-set the layaway term end. A termEndsAt-ONLY edit stays legal while placed|accruing (the term is schedule, not content)." termEndsAt: String "The wholesale line replacement (live-edit-state only) — same shape + refinements as create; MAY be emptied (a cleared cart)." lines: [OrderLineInput!] } "How the invoiced order priced its tax — captured ONCE at issue: exclusive = sales_tax adds on top; inclusive = vat_gst lives inside the captured prices." enum InvoiceTaxMode { exclusive inclusive } "One IMMUTABLE Invoice line — the issue-time snapshot of ONE order line's captured facts for the invoiced quantity; money figures are EXACT cumulative-telescoping shares (a full invoicing sums to the order line exactly, per component)." type InvoiceLine { "1-based position within THIS invoice." lineNo: Int! "The invoiced order line's frozen lineNo — the (orderId, orderLineNo) cross-document coordinate." orderLineNo: Int! "The sold variant (copied — XOR openItemDescription)." variantId: ID "The open-item description (copied — XOR variantId)." openItemDescription: String "The order line's resolved tax category (copied — the recompute coordinate)." taxCategory: TaxCategory! "The INVOICED quantity (positive decimal string; ≤ the un-invoiced remainder at issue)." quantity: String! "The captured unit sale price in minor units (copied VERBATIM — a per-unit fact)." capturedUnitPriceMinor: Int! "DERIVED: taxableBase + lineDiscount + orderDiscountShare (the identity holds by construction)." baseMinor: Int! lineDiscountMinor: Int! orderDiscountShareMinor: Int! "This invoice's telescoping share of the order line's taxable base — the note-delta axis." taxableBaseMinor: Int! "DERIVED mode-aware: exclusive ⇒ taxableBase + tax; inclusive ⇒ taxableBase (tax inside)." lineTotalMinor: Int! "The tax snapshot — the order line's slot with each component's taxMinor telescoping-prorated (rates/refs verbatim)." tax: OrderLineTax! "The cumulative SIGNED note deltas addressed to this line (absent = 0; CreditNotes subtract, DebitNotes add) — stamped by note issue/void, never caller data." notedBaseDeltaMinor: Int } "A sales Invoice — the billing/revenue-recognition document generated from an Order: an IMMUTABLE line snapshot at issue (captured prices/discounts/tax COPY, telescoping-prorated exactly for the 1..N partial model — a full invoicing sums to the order figures EXACTLY). One order → one-or-many invoices. Born issued by the bespoke issueInvoice op; corrections are NEW CreditNote/DebitNote documents, NEVER an edit — no update surface exists. The GAAP recognition trail is reports-only; the three rollup vectors are ANIMATED derived read-models." type Invoice { id: ID! "The group-scoped human-facing system id (IN-…)." sysId: String! type: String! caption: String! "The FSM state: issued | closed | voided." status: String! "The ORDER's parent — the LF or org; for an Invoice parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The invoiced Order." orderId: ID! "The selling Organization (copied from the Order at issue — attribution)." organizationId: ID! "The order currency (copied at issue; FX never touches captured figures)." currency: String! "The pricing mode captured at issue — exclusive (sales_tax adds on top) or inclusive (vat_gst inside the captured prices); the note recompute reads THIS." taxMode: InvoiceTaxMode! "The order's inline customer capture, copied at issue." customer: OrderCustomer "The order's captured ORIGIN jurisdiction, copied at issue (audit)." taxJurisdictionId: ID "The payment rollup, ANIMATED: unpaid → partial → paid — FIFO-by-issue money coverage derived from the Order’s net tenders (closed invoices pin first; a refund walks an ISSUED invoice back honestly — the newest invoice regresses first)." paymentState: String! "The fulfillment rollup, ANIMATED: unfulfilled → partial → fulfilled — per-line FIFO delivery allocation over the Order’s fulfilledQty stamps." fulfillmentState: String! "The recognition rollup, ANIMATED: deferred → partial → recognized — the deposits-until-delivery conversion; mirrors the fulfillment allocation until fiscal/service chunks diverge them. recognized + paid flips the invoice closed (system:fully_recognized_and_settled)." recognitionState: String! "Σ snapshot-line bases in minor units (exact telescoping shares)." subtotalMinor: Int! "Σ snapshot-line discount shares (line + order-level), minor units." discountTotalMinor: Int! "Σ snapshot-line tax in minor units (INSIDE the captured figures under inclusive taxMode — disclosed, not double-counted)." taxTotalMinor: Int! "The invoiced total in minor units (mode-aware line totals summed)." totalMinor: Int! "The IMMUTABLE snapshot lines (1..45); the notedBaseDeltaMinor rollups are the ONE post-issue stamp lane." lines: [InvoiceLine!]! } "One page of the invoices listing — the records + the opaque resume cursor." type InvoicePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Invoice!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One RECOMPUTED tax component on a note delta line — rate/refs copy the invoice line's CAPTURED component VERBATIM (no re-sourcing); taxMinor is SIGNED (mirrors the base delta's sign). Shared by CreditNote and DebitNote." type NoteDeltaTaxComponent { taxRateId: ID! jurisdictionId: ID! category: TaxCategory! treatment: TaxTreatment! ratePpm: Int! compound: Boolean! combined: Boolean! "SIGNED — CreditNote components ≤ 0, DebitNote components ≥ 0." taxMinor: Int! } "One STORED note delta line — the signed correction addressed to ONE invoice line (CreditNote strictly negative, DebitNote strictly positive; the sign lives on the document). Shared by both note constructs." type NoteDeltaLine { "1-based position within THIS note." lineNo: Int! "The corrected invoice line (1-based on the superseded Invoice)." invoiceLineNo: Int! "The invoice line's order coordinate (copied — the Order → Invoice → note audit chain)." orderLineNo: Int! "The invoice line's tax category (copied — the recompute coordinate)." taxCategory: TaxCategory! "The SIGNED base delta on the taxableBase axis." baseDeltaMinor: Int! "The SIGNED recomputed tax delta = Σ components (computeNoteDeltaTax over the CAPTURED components)." taxDeltaMinor: Int! taxComponents: [NoteDeltaTaxComponent!]! "The SIGNED line total delta — exclusive ⇒ base + tax; inclusive ⇒ base (tax inside)." totalDeltaMinor: Int! } "A CreditNote — the REDUCING corrective document for an issued, immutable Invoice: a NEW document carrying the SIGNED delta (every figure strictly NEGATIVE — the sign lives on the document), never an edit. The tax delta recomputes over the invoice line's CAPTURED components (a correction re-prices the SAME fact, not a new sourcing) — a FULL credit mirrors the original figures EXACTLY (the sign-symmetric arms). Over-credit refuses per line STRICT (taxableBase + Σ prior signed deltas ≥ 0). NO inventory movement — a goods-back is a Return. AR effects =; fiscalization seq/sig = (named deferrals)." type CreditNote { id: ID! "The group-scoped human-facing system id (CR-…)." sysId: String! type: String! caption: String! "The FSM state: issued | closed | voided." status: String! "The corrected Invoice's parent — the LF or org: an order-context SIBLING of the invoice it corrects (the invoiceId ref binds); for a CreditNote parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The superseded Invoice." invoiceId: ID! "The invoiced Order (copied from the invoice — the document-graph audit chain)." orderId: ID! "The selling Organization (copied — attribution)." organizationId: ID! "The invoice currency (copied — deltas re-price the SAME fact in the SAME currency)." currency: String! "The REQUIRED audit reason." reason: String! "The settlement rollup — born unsettled (the / writers widen it; dormant)." settlementState: String! "Σ line base deltas (SIGNED — strictly negative here)." baseDeltaTotalMinor: Int! "Σ line tax deltas (SIGNED — the recompute mirror)." taxDeltaTotalMinor: Int! "Σ line total deltas (SIGNED) — the note's net effect on what the customer owes." totalDeltaMinor: Int! "The signed delta lines (1..45; every base delta strictly negative — the reducing arm)." lines: [NoteDeltaLine!]! } "One page of the creditNotes listing — the records + the opaque resume cursor." type CreditNotePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CreditNote!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "A DebitNote — the INCREASING corrective twin of the CreditNote (customer owes MORE — an undercharge correction, post-billing freight, an upward price adjustment): identical lifecycle + delta mechanics, OPPOSITE sign (every figure strictly POSITIVE). The tax delta recomputes over the invoice line's CAPTURED components; NO over-credit ceiling (an increase raises the invoice's remaining net — the CreditNote guard reads the raised headroom via the same cumulative stamps). NO inventory movement. Reuses the CreditNote's NoteDeltaLine/NoteDeltaTaxComponent SDL types (the /VendorInvoice entry-order precedent)." type DebitNote { id: ID! "The group-scoped human-facing system id (DN-…)." sysId: String! type: String! caption: String! "The FSM state: issued | closed | voided." status: String! "The corrected Invoice's parent — the LF or org: an order-context SIBLING (the invoiceId ref binds); for a DebitNote parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The superseded Invoice." invoiceId: ID! "The invoiced Order (copied from the invoice — the document-graph audit chain)." orderId: ID! "The selling Organization (copied — attribution)." organizationId: ID! "The invoice currency (copied — deltas re-price the SAME fact in the SAME currency)." currency: String! "The REQUIRED audit reason." reason: String! "The settlement rollup — born unsettled (the / writers widen it; dormant)." settlementState: String! "Σ line base deltas (SIGNED — strictly positive here)." baseDeltaTotalMinor: Int! "Σ line tax deltas (SIGNED — the recompute mirror)." taxDeltaTotalMinor: Int! "Σ line total deltas (SIGNED) — the note's net effect on what the customer owes." totalDeltaMinor: Int! "The signed delta lines (1..45; every base delta strictly positive — the increasing arm)." lines: [NoteDeltaLine!]! } "One page of the debitNotes listing — the records + the opaque resume cursor." type DebitNotePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [DebitNote!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The canned saga process kinds. transfer / po_receipt are Phase-B RETROACTIVE names for the / document-FSM saga instances (naming only — their FSMs stand)." enum SagaType { checkout transfer po_receipt special_order_sourcing fiscalization_clearance } "One saga participant ref — a construct this saga's steps touch; constructType is the type name so the id resolves without guessing the family." type SagaParticipant { constructType: String! id: ID! } "One compensation-log line — appended while the saga is compensating (audit trail; the failed terminal's last line records why compensation could not complete)." type SagaCompensationEntry { "The action instant (UTC ISO-8601)." at: String! "What the compensating step did (or why compensation failed)." action: String! } "A Saga — the cross-boundary / multi-step mutation record-of-truth: each step advances status AND commits its effect in ONE transaction; the record IS the durable state machine. Isolation = the semantic lock. SYSTEM-MINTED end to end: the wire is READ-ONLY (no create/edit/transition mutations exist — lifecycle is kit-channel; the first live records mint with the first genuinely multi-step process, checkout). failed is the terminal — compensation itself could not complete; recovery is a NEW linked saga, never a resurrection." type Saga { id: ID! "The group-scoped human-facing system id (SG-…)." sysId: String! type: String! caption: String! "The FSM state: pending | running | compensating | completed | compensated | failed." status: String! "The parent org group; for a Saga parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned process kind. IMMUTABLE at birth." sagaType: SagaType! "The aggregate the semantic lock isolates — e.g. the Order under checkout. IMMUTABLE at birth." lockAggregateId: ID! "The construct refs this saga's steps touch (1..32, distinct). IMMUTABLE at birth." participants: [SagaParticipant!]! "The compensation audit log (born empty; appends while compensating, ≤ 64 — the failed terminal's last line records why). Server data, never caller-writable." compensationLog: [SagaCompensationEntry!]! "Null on SF-less sagas (document-FSM instances) and the degraded lane. The ops/reconcile handle." sfExecutionArn: String "The LIVE WaitForTaskToken callback token. Present ⟺ the execution is paused at the external wait; kit-stamped." taskToken: String } "One page of the sagas listing — the records + the opaque resume cursor." type SagaPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Saga!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The per-line receive dispositions: restock → on_hand (resellable) · inspect → held · damaged → damaged · scrap → WRITE-OFF (no bucket; the unit never re-enters stock — reports-only)." enum ReturnDisposition { restock inspect damaged scrap } "The refund routing methods. Recording only — mechanics //." enum ReturnRefundMethod { original_tender cash store_credit } "One receive-time disposition split on a return line (Σ per line == the line quantity — exact cover, splits across codes legal)." type ReturnLineDisposition { disposition: ReturnDisposition! "The quantity under this code (positive decimal string, the line stock UoM)." quantity: String! "The disposition reason — REQUIRED for non-restock codes." reason: String } "One Return line — the request-time identity copy of ONE order line's returned quantity (whole units) + the RECEIVE-time stamps (disposition cover · the telescoping refund money over the order line's captured figures · the restocking fee). Stamps are server-written, never caller data." type ReturnLine { "1-based position within this return." lineNo: Int! "The returned order line's frozen lineNo — the (orderId, orderLineNo) cross-document coordinate." orderLineNo: Int! "The sold variant (copied — XOR openItemDescription)." variantId: ID "The open-item description (copied — stockless: no disposition, no movement; refund-only)." openItemDescription: String "The order line's resolved tax category (copied — the remittance-reversal coordinate)." taxCategory: TaxCategory! "The returned quantity (positive decimal string; bindingly bounded at receive: quantity − returnedQty)." quantity: String! "The request-time reason (why the customer returns)." reason: String "The receive-time disposition cover (absent until received; ALWAYS absent on stockless lines)." dispositions: [ReturnLineDisposition!] "RECEIVE-stamped: this return's telescoping share of the order line's lineTotalMinor (the paid value — tax inside, both regimes)." paidShareMinor: Int "RECEIVE-stamped: halfAway(paidShare × the order line's captured restockingFeePpm / 1e6); absent when the line captured no fee flag." restockingFeeMinor: Int "RECEIVE-stamped: paidShare − restockingFee, floored at 0 — this line's refund." refundMinor: Int "RECEIVE-stamped: the order line's tax slot with each component's taxMinor telescoping-prorated (rates/refs verbatim) — the remittance-reversal report source." tax: OrderLineTax } "The refund routing record — stamped by refundReturn/posReturn." type ReturnRefund { method: ReturnRefundMethod! "Optional external reference (a processor id / credit-slip number)." reference: String "The drawer session a CASH refund paid out of." tillSessionId: ID "The Refund children the original_tender processor walk committed for THIS return." refundIds: [ID!] "The store_credit instrument this refund MINTED." mintedInstrumentId: ID } "A sales Return / RMA — the customer→merchant goods-back document (distinct from vendor RTV; the disjoint law: a billing correction is a CreditNote/DebitNote, never a Return). References the original Order (+ optionally one of its Invoices); returns WHOLE units of order lines; receive posts per-line disposition legs at the RECEIVING LF and stamps the telescoping refund money; refund RECORDS the routing (tender mechanics; store-credit issuance)." type Return { id: ID! "The group-scoped human-facing system id (RT-…)." sysId: String! type: String! caption: String! "The FSM state: requested | approved | received | refunded | closed | cancelled | rejected." status: String! "The processing/receiving LogicalFacility; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The returned Order." orderId: ID! "Optional Invoice ref (receipted returns) — belongs to orderId, gated at create." invoiceId: ID "The selling Organization (copied from the Order at create — attribution)." organizationId: ID! "The order currency (copied at create; refunds never cross currency)." currency: String! "The order's inline customer capture, copied at create (identity on the RMA — audit)." customer: OrderCustomer "RECEIVE-stamped: Σ line refundMinor — the total owed back (absent until received)." refundTotalMinor: Int "REFUND-stamped: the routing record (amount = refundTotalMinor; state = the FSM)." refund: ReturnRefund "The return lines (1..45); each refs an order line by its frozen lineNo." lines: [ReturnLine!]! } "One page of the returns listing — the records + the opaque resume cursor." type ReturnPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Return!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One caller line at create / wholesale replace — (orderLineNo, quantity[, reason]); distinct orderLineNos; positive quantities. Lines flagged nonReturnable/finalSale refuse CONFLICT/NOT_RETURNABLE naming the flag." input ReturnLineInput { orderLineNo: Int! quantity: String! reason: String } "Create-input to request a Return. The org (ACTIVE) + the receiving LF (ACTIVE, same spine) + the order (same-group, ∈ {placed, completed}) + the optional invoice (belongs to the order) are gated live; nonReturnable/finalSale lines refuse CONFLICT/NOT_RETURNABLE; the returnable remainder pre-checks at create (NON-binding — the BINDING check is the receive stamp)." input NewReturnInput { "Optional: when omitted the per-type default applies — the order sysId + line count (return of SO-… 2 lines); when supplied it must be non-blank." caption: String "The Order being returned against — same-group; ∈ {placed, completed} (CONFLICT/REF_STATE else)." orderId: ID! "Optional Invoice ref — same-group + must belong to the order (the receipted-return audit edge)." invoiceId: ID "The processing/receiving LF — becomes the parent." logicalFacilityId: ID! "The returned lines (1..45, distinct orderLineNos)." lines: [ReturnLineInput!]! } "Edit-input for a Return. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). REQUESTED-ONLY: after approve the request is fixed (receive binds dispositions); a supplied lines array REPLACES wholesale and re-runs the create refinements + eligibility gates." input EditReturnInput { caption: String "The wholesale line replacement (requested-only) — same shape + refinements as create." lines: [ReturnLineInput!] } "A Register — a POS terminal / till position at a LogicalFacility: the LOGICAL till identity TillSessions parent to (physical device pairing =, one-way Device→Register — never stored here). The OPERATIONAL lifecycle verbatim. The gate: a LIVE TillSession (open/suspended/counting) blocks deactivate AND doom, CONFLICT/REFERENCED naming it; terminal sessions never block." type Register { id: ID! "The group-scoped human-facing system id (RG-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent LogicalFacility; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the registers listing — the records + the opaque resume cursor." type RegisterPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Register!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Register. The tenant (org group) is derived SERVER-SIDE from the principal; logicalFacilityId (the parent — rides the header) is tenant-scoped server-side and must be ACTIVE (any LF classification — does not restrict registers to store-class LFs)." input NewRegisterInput { "Optional: when omitted the per-type default applies — the LF coordinate ('register at '); when supplied it must be non-blank." caption: String "The parent LogicalFacility (the till position's home) — tenant-scoped + ACTIVE. Immutable after birth." logicalFacilityId: ID! code: String } "Edit-input for a Register. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). The parent LF is NOT editable (IMMUTABLE at birth — a till position does not move facilities; re-home = create + doom)." input EditRegisterInput { caption: String code: String } "One per-currency drawer figure. Non-negative on float/counted; SIGNED on drawerTotals/overShort." type DrawerAmount { currency: String! amountMinor: Int! } "The 9 canned drawer entry types. recordCashEntry accepts the MANUAL subset only (paid_in | paid_out | drop | pickup); float_in/count_adjust are open/close-posted; cash_sale/cash_refund/change_given post ONLY through the tender writers (applyTender/refundTender/the Return refund writers)." enum CashEntryType { float_in cash_sale cash_refund paid_in paid_out drop pickup change_given count_adjust } "The FX capture: the entry's own currency/amountMinor ARE the foreign holding; this block adds the exact rate applied + the settlement value BOOKED at the till rate — the left operand of the future realized-gain/loss computation (the banking/drop realization = a later slice). Rides the FOREIGN cash_sale entry only." type CashEntryFx { "The WINNING FxRate record consumed." rateId: ID! "The COMPOSED effective buy rate applied, integer micro to-per-from." rateMicro: Int! "The settlement (org default) currency the sale booked in." settledCurrency: String! "The settlement-currency minor units this foreign holding booked at (converted − fees)." settledMinor: Int! } "ONE posted cash-drawer ledger fact: the SIGN is the direction (positive = cash INTO the drawer). sysId-LESS (the class); IMMUTABLE — NO update or doom op exists (corrections are NEW compensating entries); posted ONLY by openTillSession (float_in), recordCashEntry (the manual subset), closeTillSession (count_adjust), and the tender writers (cash_sale/cash_refund/change_given) — each in ONE transaction with the drawerTotals cache stamp." type CashEntry { id: ID! type: String! "The derived display caption — entryType + currency + signed minor; never editable." caption: String! "The FSM state: active | doomed (doomed = VOIDED, reserved for a future void-family flow)." status: String! "The parent TillSession." parentId: ID! rootId: ID! "The canned entry type (SPEC_REGISTRY — the sign law rides it)." entryType: CashEntryType! "The entry currency (the per-currency drawer; FX capture fields arrive with the writers)." currency: String! "The SIGNED minor-unit amount — the sign IS the drawer direction." amountMinor: Int! "The reason — REQUIRED on the manual ops; auto-generated on float_in/count_adjust." reason: String "The GL expense/income category — rides paid_in/paid_out only." glCategory: String "Provenance document refs (bounded free strings — typed refs land with their writers)." refs: [String!] "The FX capture (foreign cash_sale entries only)." fx: CashEntryFx "Present (true) EXACTLY when this entry drove its currency's drawer total negative." overdrawn: Boolean createdAt: String! updatedAt: String! revision: ID! revisionNum: Int! } "A TillSession — the cash-drawer session at a Register: opened by a User with a counted starting float, tracking float / expected / counted / over-short through the immutable CashEntry ledger (the Stock-Card discipline — nothing changes the drawer without a ledger entry). ONE live session per register (STRICT — the tillSession marker). Expected cash = the drawerTotals cache, stamped in the SAME transaction as every entry post. The shift IS this doc (openedBy + createdAt→closedAt); X/Z report ARTIFACTS are the reports family." type TillSession { id: ID! "The group-scoped human-facing system id (TS-…)." sysId: String! type: String! caption: String! "The FSM state: open | suspended | counting | closed | abandoned." status: String! "The parent Register; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The opening User, server-stamped from the principal." openedBy: ID! "The declared opening float, verbatim." float: [DrawerAmount!]! "The per-currency running drawer totals. Expected cash = this list." drawerTotals: [DrawerAmount!]! "CLOSE-stamped: the counted drawer, verbatim." counted: [DrawerAmount!] "CLOSE-stamped: counted − expected per currency (negative = short, positive = over; each non-zero figure posted a count_adjust entry)." overShort: [DrawerAmount!] "The terminal instant (stamped at close AND abandon — the shift period's end)." closedAt: String "The no_sale audit trail — drawer-opened-without-sale count; absent = none." noSaleCount: Int "The most recent no-sale instant (rides every noSale stamp)." lastNoSaleAt: String } "One page of the tillSessions listing — the records + the opaque resume cursor." type TillSessionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TillSession!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One per-currency figure." input DrawerAmountInput { currency: String! amountMinor: Int! } "An ApprovalRequest — the real-time, human-approver, in-session authorization of ONE POS action exceeding the requester's authority (DISTINCT from the async ChangeRequest). The blocked action stays blocked until resolved; short TTL (expiresAt — a touch past it refuses CONFLICT/EXPIRED and lazily expires the request). The request binds a fingerprint (action, targetId[, valueMinor]) + the requester: on approval, RETRYING the identical gated call finds + consumes the approval by fingerprint (single-use — the marker releases in the retry's own transaction). Never self-approve (AUTHZ/SELF_APPROVAL); an under-ranked approver is AUTHZ/INSUFFICIENT." type ApprovalRequest { id: ID! "The group-scoped human-facing system id (AR-…)." sysId: String! type: String! caption: String! "The FSM state: pending | approved | denied | expired | cancelled." status: String! "deterministic parent: the open TillSession when the action runs in a till session, else the LF; rootId = the org group regardless." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The gated action: discount.apply · price.override · void.line · void.transaction · return.approve · sale.restricted_item · no_sale · oversell · refund.routing_exception · credit.over_limit · order.below_minimum. Live: discount.apply · void.transaction · return.approve · no_sale · refund.routing_exception · credit.over_limit · order.below_minimum; the rest refuse VALIDATION/UNSUPPORTED naming their arrival." action: String! "The target construct type — derived from the action, stored for the fingerprint." targetType: String! "The blocked action's target construct." targetId: ID! "The bound value (integer minor units) when the action carries one — discount.apply binds the discount Σ, EXACT-matched at consumption; absent for whole-target actions." valueMinor: Int "The requesting User." requestedBy: ID! "The REQUIRED approver tier; the approver's resolved tier rank must be ≥ this tier's rank (AUTHZ/INSUFFICIENT below it)." requiredTier: RoleTemplateKey! "Why the requester needs the override." reason: String! "The live-window end (createdAt + the 900s TTL, ISO-8601): approve/deny/consume past it refuse CONFLICT/EXPIRED and the request lazily expires." expiresAt: String! "DECISION-stamped: the approving/denying User (≠ requestedBy on approve — never-self-approve)." decidedBy: ID "DECISION-stamped: the decision instant (ISO-8601)." decidedAt: String "DECISION-stamped: the approver/denier's stated reason (optional — the transition template)." decisionReason: String } "One page of the approvalRequests listing — the records + the opaque resume cursor." type ApprovalRequestPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ApprovalRequest!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The EFFECTIVE resolved rate for one (fromCurrency → org default) pair at one instant: the WINNING most-specific record's identity + window, with the COMPOSED figures (adjustment chains folded in, fees accumulated)." type FxResolution { "The winning (most-specific covering) FxRate record — the rate-on-every-event ref target." rateId: ID! "The winning record's level (group | org | lf)." level: String! fromCurrency: String! toCurrency: String! "The COMPOSED effective buy rate, integer micro to-per-from." buyRateMicro: Int! "The COMPOSED effective sell rate, integer micro to-per-from." sellRateMicro: Int! "The accumulated adjustment fees along the chain, TO-currency minor units (0 = none)." feeMinor: Int! "The winning record's window." startAt: String! endAt: String! } "An FX rate window: ONE effective-dated conversion rate record in the tenant schedule, resolved group (default) → org → LF MOST-SPECIFIC-WINS at every conversion event. Modes: absolute (explicit buy/sell integer-micro rates — the ONLY group-level mode) · adjust (± ppm over the next-less-specific EFFECTIVE rate, both directions, optional fee) · par (1:1). Doom cancels a not-yet-effective FUTURE record only (CONFLICT/IMMUTABLE otherwise — supersede instead). The window/pair/mode/rate fields are wire-IMMUTABLE (the edit surface is caption only). Consumed by the foreign_cash tender lane at the BUY side." type FxRate { id: ID! "The group-scoped human-facing system id (FX-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The level anchor: the org group itself (group level — parentId === rootId), an Organization, or a LogicalFacility." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The resolution level this record binds (group | org | lf — most-specific-wins). Stored explicit, validated against the REAL parent at create; IMMUTABLE." level: String! "The FROM (tendered/foreign) currency; registry-gated at create. IMMUTABLE — supersede to change." fromCurrency: String! "The TO (settlement) currency — the org default currency at resolution. IMMUTABLE." toCurrency: String! "The record mode (absolute | adjust | par — override grammar; group-level records are absolute). IMMUTABLE." mode: String! "ABSOLUTE only: the rate WE BUY the from-currency at, integer micro to-per-from (1.25 = 1250000). IMMUTABLE." buyRateMicro: Int "ABSOLUTE only: the rate WE SELL the from-currency at, integer micro to-per-from. IMMUTABLE." sellRateMicro: Int "ADJUST only: the SIGNED ± ppm applied to BOTH directions (buy AND sell) of the next-less-specific effective rate. IMMUTABLE." adjustPpm: Int "ADJUST only, optional: a fee in TO-currency minor units, REDUCING the credited amount at conversion. IMMUTABLE." feeMinor: Int "The window start (INCLUSIVE; UTC ISO-8601) — set at birth (absent in the create input = effective NOW, server-stamped), IMMUTABLE thereafter." startAt: String! "The window end (EXCLUSIVE; UTC ISO-8601; ALWAYS present — far-future = the standing rate). Moves ONLY via the system splice trim." endAt: String! } "One page of the fxRates listing — the records + the opaque resume cursor." type FxRatePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [FxRate!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an FxRate. The tenant (org group) is derived SERVER-SIDE from the principal; the LEVEL is named by the anchor field: BOTH absent = a group-level record, organizationId = an org override, logicalFacilityId = an LF override (naming both refuses). The anchor is tenant-scoped server-side and must be ACTIVE; BOTH currencies must be in the minor-unit registry (VALIDATION/UNSUPPORTED_CURRENCY naming the side); group-level records must be absolute; startAt is optional (absent = effective NOW, server-stamped; explicit values must be >= the server now — no past starts) and must precede endAt." input NewFxRateInput { "Optional: when omitted the per-type default applies — the window coordinate `/ from `; when supplied it must be non-blank." caption: String "The org anchor for an ORG-level override — tenant-scoped server-side; absent (with logicalFacilityId absent) = a GROUP-level record." organizationId: ID "The LF anchor for an LF-level override — tenant-scoped server-side; never together with organizationId." logicalFacilityId: ID "The FROM (tendered/foreign) currency — must be in the minor-unit registry." fromCurrency: String! "The TO (settlement) currency — must be in the registry; must differ from fromCurrency." toCurrency: String! "absolute (buy+sell required) | adjust (adjustPpm required, feeMinor optional; org/LF only) | par (no rate fields; org/LF only)." mode: String! "ABSOLUTE only — integer micro to-per-from (1.25 = 1250000)." buyRateMicro: Int "ABSOLUTE only — integer micro to-per-from." sellRateMicro: Int "ADJUST only — SIGNED, non-zero, ±500000 (±50%)." adjustPpm: Int "ADJUST only, optional — TO-currency minor units, reducing the credited amount." feeMinor: Int "The window start (INCLUSIVE; UTC ISO-8601). Optional — absent = effective NOW (server-stamped); explicit values must be >= the server now (no past starts)." startAt: String "The window end (EXCLUSIVE; UTC ISO-8601). ALWAYS required (far-future = the standing rate); must be strictly after startAt." endAt: String! } "Edit-input for a FxRate. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet). The window/pair/mode/rate fields are NOT editable (wire-IMMUTABLE facts, supersede with a new window or doom a FUTURE record and re-create; the system splice trim is the ONE sanctioned endAt move)." input EditFxRateInput { caption: String } "The DOC-shaped delivery lanes: ship (carrier; ship = delivered) · pickup_curbside / pickup_instore (BOPIS — stage then handover). carryout never creates a Fulfillment (the till lane); a deliver_later/special_order line capture may fulfill via ANY lane; dropship is the named deferral." enum FulfillmentMethod { ship pickup_curbside pickup_instore } "One Fulfillment line — the create-time identity copy of ONE order line's claimed quantity (partial + split legal: the BINDING remainder gate reads the Order's own fulfillmentClaimedQty stamp). Lines are immutable at birth — re-scope = cancel + create." type FulfillmentLine { "1-based position within this fulfillment." lineNo: Int! "The fulfilled order line's frozen lineNo — the (orderId, orderLineNo) cross-document coordinate." orderLineNo: Int! "The sold variant (copied — XOR openItemDescription; the pick/pack identity)." variantId: ID "The open-item description (copied — stockless: delivery stamps, no stock movement)." openItemDescription: String "The claimed quantity (positive decimal string; ≤ the order line's unclaimed remainder at create)." quantity: String! } "The inline ship-to snapshot. REQUIRED effective at ship for method=ship; refused on pickup docs." type FulfillmentShipTo { name: String! "The street address (1..3 lines)." addressLines: [String!]! city: String! "The region / state / province (optional — not every country subdivides)." region: String postalCode: String "ISO-3166-1 alpha-2, uppercase." countryCode: String! phone: String } "A Fulfillment — groups order lines fulfilled together by ONE method from ONE LF: pick → pack → ship-or-stage → deliver. Ship = delivered (the operator ruling — the ship call fires BOTH edges); delivery relieves stock through the sell-relief lane (release of the ecom reserve rides it), stamps the ORDER line fulfilledQty rollups, and recomputes both delivery vectors; the completion evaluator flips a paid-and-delivered order to completed. After `pack` the record IS the Packing-List node (packedAt + the immutable lines; the FF-… sysId is the document number). Carryout lines NEVER ride a Fulfillment (the paid-completion till lane); dropship + ship-from-other-store are the named /Transfer-composition deferrals." type Fulfillment { id: ID! "The group-scoped human-facing system id (FF-…)." sysId: String! type: String! caption: String! "The FSM state: pending | picking | packed | shipped | ready_for_pickup | fulfilled | cancelled." status: String! "The fulfilling LogicalFacility; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The fulfilled Order." orderId: ID! "The selling Organization (copied from the Order at create — attribution)." organizationId: ID! "The delivery lane — decides the packed→[shipped | ready_for_pickup] conditional edge." method: FulfillmentMethod! "The inline ship-to snapshot (method=ship — captured at create or at ship; the ship payload wins as the label truth)." shipTo: FulfillmentShipTo "SHIP-stamped carrier capture (carrier-API integration is build-time-flagged)." carrierName: String "SHIP-stamped tracking reference capture." trackingRef: String "PACK-stamped: the Packing-List instant (the document node = this record after pack)." packedAt: String "The claimed lines (1..45); each refs an order line by its frozen lineNo." lines: [FulfillmentLine!]! } "One page of the fulfillments listing — the records + the opaque resume cursor." type FulfillmentPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Fulfillment!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One caller line at create — (orderLineNo, quantity); distinct orderLineNos; positive quantities; quantity ≤ the line's unclaimed remainder (quantity − fulfillmentClaimedQty, the BINDING port gate). Lines whose captured method is incompatible with the doc lane refuse VALIDATION/INVALID naming the pair (carryout lines never join — the till lane delivers them)." input FulfillmentLineInput { orderLineNo: Int! quantity: String! } "The inline ship-to capture (method=ship only — strict both ways; suppliable at create or at ship, the ship payload replacing as the label truth)." input FulfillmentShipToInput { name: String! addressLines: [String!]! city: String! region: String postalCode: String countryCode: String! phone: String } "Create-input for a Fulfillment. The org (ACTIVE) + the order (same-group, placed, orderType sale) are gated live; the fulfilling LF is the ORDER’s OWN LF (derived server-side — ship-from-other-store is the named Transfer-composition deferral); each line’s captured method must be lane-compatible and its quantity within the unclaimed remainder; the create transaction stamps the Order’s fulfillmentClaimedQty rollups under the Order’s OCC." input NewFulfillmentInput { "Optional: when omitted the per-type default applies — the method + order coordinate (ship fulfillment of SO-… 2 lines); when supplied it must be non-blank." caption: String "The Order being fulfilled — same-group; placed + sale (CONFLICT/REF_STATE else)." orderId: ID! "The delivery lane (ship | pickup_curbside | pickup_instore)." method: FulfillmentMethod! "The inline ship-to (method=ship only — may also arrive at ship; strict both ways)." shipTo: FulfillmentShipToInput "The claimed lines (1..45, distinct orderLineNos)." lines: [FulfillmentLineInput!]! } "A Payment — a PROCESSOR-backed payment (the integrated processing mode), spawned by a card Tender. Aligned to the deposit→recognition model: authorize = the hold = DEPOSIT at tender; capture = RECOGNIZED at delivery — POS carry-out collapses authorize+capture by ARRIVING at delivery in the same request (the settle instant delivers), never by skipping states. Record-first/processor-after: minted created BEFORE any processor call; the StripePort attempt fires post-commit; state flips ride the ACK/webhook path; 32 attempts bound each order (the Order.paymentIds cap). PCI-min: the PAN never touches AT/stack — the record holds the opaque tokenized methodRef + processor refs + at most brand/last4. The StripePort is FAKED at 7.7a (deterministic, keyless); the live adapter + webhook ingress are 7.7b." type Payment { id: ID! "The group-scoped human-facing system id (PY-…)." sysId: String! type: String! caption: String! "The FSM state: created | authorized | captured | succeeded | failed | cancelled | voided." status: String! "The Order this payment settles; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selling Organization (copied from the Order at mint — attribution)." organizationId: ID! "The amount APPLIED toward the order balance in minor units (positive — the spawning tender appliedMinor twin)." amountMinor: Int! "The tip portion charged ON TOP of amountMinor." tipMinor: Int "The settlement currency — the order currency snapshot." currency: String! "The opaque tokenized payment method presented (Stripe pm_… class — NEVER a PAN; the raw-card shape refuses at the boundary)." methodRef: String! "The spawned Tender row — stamped WITH the authorize flip (present from authorized onward)." tenderId: ID "The Connect account this payment routes DIRECT on (acct_…; stamped at MINT from the selling org when chargeable). Null = the platform account. Capture/cancel/refund thread THIS stamp — immutable payment history." stripeAccountRef: String "The orchestrating checkout Saga: its WaitForTaskToken owns the capture instant. Null = the inline capture lanes own this payment (the bulkhead)." sagaId: ID "The processor PaymentIntent ref — stamped from the authorize ACK (present from authorized onward)." intentRef: ID "The processor charge ref — stamped from the capture ACK (present from captured onward)." chargeRef: ID "The card brand as the PROCESSOR reported it (PCI-min — never caller-typed)." brand: String "The last four digits as the PROCESSOR reported them." last4: String "The processor decline/failure reason (failed payments only)." declineReason: String } "One page of the payments listing — the records + the opaque resume cursor." type PaymentPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Payment!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "A Refund — a PROCESSOR-executed money reversal against the original Payment. NEVER wire-created: it spawns inside refundReturn(original_tender) — and its posReturn collapse — record-first/processor-after: minted created BEFORE the StripePort.refund call; the settle/fail flips ride the ACK/webhook path (system:stripe_webhook rows ONLY — the wire surface is READ-ONLY); 64 attempts bound each order (the Order.refundIds cap). Allocation is LIFO over the order's refundable integrated payments (newest money first); over-capacity refuses CONFLICT/OVER_TENDERED; each committed refund posts a NEGATIVE card Tender. An async processor failure composes the compensating-tender unwind + the refund_async_failed operational line." type Refund { id: ID! "The group-scoped human-facing system id (RF-…)." sysId: String! type: String! caption: String! "The FSM state: created | succeeded | failed." status: String! "The Payment whose settled money this reverses; the record also names its spawning Return (returnId) and the Order anchoring the money story (orderId); rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selling Organization (copied from the parent Payment at mint — attribution)." organizationId: ID! "The Order anchoring the money story (the parent Payment’s own parent — the Order.refundIds bounded-append twin)." orderId: ID! "The Return this refund executes (SPEC_CATALOG:365 Refund→Return N:1 — the refundReturn original_tender spawn; the RETURN lane is the ONLY refund consumer)." returnId: ID! "The amount reversed in minor units (positive — the sign lives on the reversal Tender row)." amountMinor: Int! "The settlement currency — the parent Payment’s currency VERBATIM." currency: String! "The Connect account context THREADED from the parent Payment’s stamp. Null = the platform account." stripeAccountRef: String "The processor refund ref (re_…) — stamped WITH the settle/fail truth (REQUIRED from succeeded; present on an ASYNC-failed refund, absent on a sync port refusal)." refundRef: ID "The processor failure reason (failed refunds only — sync port refusal or async processor truth)." failureReason: String } "One page of the refunds listing — the records + the opaque resume cursor." type RefundPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Refund!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "A Dispute — the Stripe chargeback lifecycle mirrored (SPEC_CATALOG 147; the / fraud-signal seed). NEVER wire-created: WEBHOOK-BORN from charge.dispute.created — the ingress resolves the parent Payment through the PI-metadata law, mints record-first (needs_response, deduped by a UNIQ reservation on disputeRef), appends Order.disputeIds (32 bound), and emits the payment_dispute_opened operational line (money-loss events are operator-mandatory). The processor holds the disputed funds while evidenceDueBy runs; won/lost land via charge.dispute.closed (an UNANSWERED dispute closing lost rides the two-edge cascade needs_response→under_review→lost — the must-pass-under_review law); on lost the funds+fee reverse REPORTS-ONLY. The TWO caller lanes carry authority:manage_dispute: submitEvidenceDispute (the evidence bespoke) and acceptDispute (concede via the processor close)." type Dispute { id: ID! "The group-scoped human-facing system id (DP-…)." sysId: String! type: String! caption: String! "The FSM state: needs_response | under_review | won | lost | accepted." status: String! "The Payment whose charge is disputed; the record also names the Order anchoring the money story (orderId); rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selling Organization (copied from the parent Payment at mint — attribution)." organizationId: ID! "The Order anchoring the money story (the parent Payment’s own parent — the Order.disputeIds bounded-append twin)." orderId: ID! "The processor dispute ref (dp_…) — REQUIRED ALWAYS (webhook-born records carry their processor identity from birth; the UNIQ mint-dedup key)." disputeRef: ID! "The disputed amount in minor units (the processor’s figure VERBATIM — may differ from the payment on partial disputes)." amountMinor: Int! "The dispute currency — the processor’s figure VERBATIM." currency: String! "The processor dispute reason code VERBATIM (e.g. fraudulent, product_not_received — the fraud-signal seed)." reason: String! "The processor’s evidence deadline (UTC ISO-8601) — operator-facing urgency; the PROCESSOR enforces it (never scheduled against, SCH-1 class)." evidenceDueBy: String "The Connect account context THREADED from the parent Payment’s stamp. Null = the platform account." stripeAccountRef: String "The evidence text submitted through the caller lane (stamped WITH the respond flip — the presence law; null on dashboard-side submissions and the accept path)." evidenceText: String } "One page of the disputes listing — the records + the opaque resume cursor." type DisputePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Dispute!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The canned effect kinds (SPEC_REGISTRY row 105 VERBATIM, generated from the contracts PROMOTION_EFFECT_TYPES SoT — anti-drift). FIVE animate; free_gift + free_shipping are the NAMED deferrals — schema-parseable, create-REFUSED (VALIDATION/UNSUPPORTED naming the kind) until their substrate (the line-add side-effect / the shipping charge) exists." enum PromotionEffectType { percent_off amount_off fixed_price buy_x_get_y bundle_combo free_gift free_shipping } "WHERE an effect's reduction lands: line = each matched line; order = ONE figure allocated largest-remainder across the MATCHED lines ONLY (unmatched lines' tax bases stay untouched)." enum PromotionEffectTarget { line order } "The buy_x_get_y get-item scope: same = rewards come from the SAME matched set (floor(units/(x+y))·y); different = from getProductScope (min(floor(buyUnits/x)·y, getUnits)); the benefit lands on the CHEAPEST eligible units — deterministic." enum PromotionBogoScope { same different } "ONE bundle component: product OR category-SUBTREE refs (OR within) + the units per combo. Lines are claimed by the FIRST component they match (array order — deterministic)." type PromotionBundleComponent { productIds: [ID!] categoryIds: [ID!] qty: Int! } "The canned effect — ONE flat render of the contracts discriminated union (the CollectionPredicate render pattern): kind selects the arm; each arm's fields are present on it and absent elsewhere. Percentages ride integer ppm (10% = 100000); amounts are integer minor units in the org default currency; effects only REDUCE — never uplift." type PromotionEffect { kind: PromotionEffectType! "percent_off: the ppm ((0, 1000000])." percentPpm: Int "amount_off: the absolute reduction (minor units)." amountMinor: Int "percent_off/amount_off: where the figure lands." target: PromotionEffectTarget "fixed_price: the target UNIT price — each matched line reduces so its running subtotal = unit × qty; already-below = no-op (LINE-only by construction)." unitPriceMinor: Int "buy_x_get_y: the buy quantity (X)." buyQty: Int "buy_x_get_y: the get quantity (Y) per reward group." getQty: Int getScope: PromotionBogoScope "buy_x_get_y getScope=different: the get-item scope (REQUIRED iff different)." getProductScope: PromotionProductScope "buy_x_get_y: ABSENT = free (100%); bundle_combo: the percent benefit (XOR benefitAmountMinor)." benefitPercentPpm: Int "bundle_combo: the amount benefit PER COMBO (× the multiplier k; largest-remainder across participants; XOR benefitPercentPpm)." benefitAmountMinor: Int "bundle_combo: the components (2..8 — a single-component qty deal is buy_x_get_y/minQty)." components: [PromotionBundleComponent!] "free_gift (DEFERRED): the gifted Variant." giftVariantId: ID "free_gift (DEFERRED): the gift quantity." qty: Int } "WHERE a promotion applies: each axis absent = unrestricted; present = the order must match (channel · the order's parent LF [POS orders] · the order's org · the order's RESOLVED CustomerPriceGroup — the arrival). priceGroupIds ABSENT = customer-blind (the default — every pre- promotion keeps its exact behavior); PRESENT = the resolved group must be IN the list (an unresolved order matches NO group-scoped promotion). The remaining customer axes (loyalty-tier / employee / Segment) stay the NAMED deferrals." type PromotionScope { channels: [OrderChannel!] logicalFacilityIds: [ID!] organizationIds: [ID!] "The CustomerPriceGroup eligibility axis." priceGroupIds: [ID!] } "WHAT product lines match: the CollectionPredicate VERBATIM + manual inclusions (union) / exclusions (subtract; included∩excluded refused) + a direct Collection ref (membership resolved PER CART LINE: static = member point-read; dynamic = pins-beat-exclusions then the collection's predicate; status-blind stored-ref matching, the EV-n law). ABSENT on the Promotion = ALL product lines (the sitewide sale — the recorded divergence); open_item lines NEVER match." type PromotionProductScope { predicate: CollectionPredicate includedProductIds: [ID!] excludedProductIds: [ID!] collectionId: ID } "WHEN a promotion fires: minQty = Σ scope-matched integer units; minSubtotalMinor = Σ matched lines' RUNNING subtotal at position 3 (after manual + coupon); required refs = ANY present in the cart (category = SUBTREE). Tiered qty breaks = MULTIPLE promotions (the recorded simplification — minQty IS the threshold)." type PromotionCartConditions { minQty: Int minSubtotalMinor: Int requiredProductIds: [ID!] requiredCategoryIds: [ID!] } "A Promotion — the rule-based discount engine that EMITS source=promo LINE discount entries at the step-2 position 3 (after manual + coupon; the pipeline math was position-complete from birth — the build ANIMATES the dormant slot, the pattern). Org restriction is JUNCTION-LESS: the scope axes (channels/LFs/orgs) gate WHERE it fires; productScope (the CollectionPredicate VERBATIM + inclusions/exclusions + a Collection ref) gates WHAT lines match — ABSENT productScope = ALL product lines (the sitewide sale; open_item lines never match); cartConditions gate WHEN. Windows are half-open [startAt, endAt) — an EVALUATION gate, never FSM states (advance scheduling = create active with a future startAt; absent endAt = evergreen). Resolution is STRICT no-stack (priority asc, id asc; combinableGroup opts IN; exclusive blocks its lines). Emissions are ABSOLUTE amount entries computed to replay VERBATIM in the pipeline; order-target effects pre-allocate largest-remainder over the MATCHED lines ONLY. Redemptions count per ORDER in the place/accept transaction; a capped-out promotion silently STOPS FIRING. At most 128 ACTIVE per org group." type Promotion { id: ID! "The group-scoped human-facing system id (PM-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Promotion parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned effect — wholesale-replace on edit; free_gift/free_shipping are the NAMED deferrals (create-refused VALIDATION/UNSUPPORTED)." effect: PromotionEffect! "WHERE it fires." scope: PromotionScope "WHAT product lines match." productScope: PromotionProductScope "WHEN it fires." cartConditions: PromotionCartConditions "The half-open window start (UTC ISO-8601; kit-stamped NOW when omitted at create — the sale-price stamp law)." startAt: String! "The half-open window end — ABSENT = evergreen (until deactivated); [startAt, endAt) is an EVALUATION gate." endAt: String "Deterministic resolution ordinal." priority: Int! "An exclusive promotion applies only to promo-free lines and permanently blocks its lines." exclusive: Boolean! "Merchant-authored stacking tag — two promotions stack on a line IFF they share this value; absent = never combines." combinableGroup: String "Per-promotion self-cap: Σ emission per LINE (minor units)." maxDiscountPerLineMinor: Int "Per-promotion self-cap: Σ emission per ORDER (largest-remainder re-clamp to EXACTLY the cap)." maxDiscountPerOrderMinor: Int "Total-redemption cap." totalRedemptionsCap: Int "TRUE ⇒ evaluates ONLY while an attached, valid trigger Coupon references it — never auto-fires." couponGated: Boolean! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } input PromotionBundleComponentInput { productIds: [ID!] categoryIds: [ID!] qty: Int! } "No further notes." input PromotionEffectInput { kind: PromotionEffectType! percentPpm: Int amountMinor: Int target: PromotionEffectTarget unitPriceMinor: Int buyQty: Int getQty: Int getScope: PromotionBogoScope getProductScope: PromotionProductScopeInput benefitPercentPpm: Int benefitAmountMinor: Int components: [PromotionBundleComponentInput!] giftVariantId: ID qty: Int } "The scope input — ≥1 axis with unique members; omit the field for unrestricted." input PromotionScopeInput { channels: [OrderChannel!] logicalFacilityIds: [ID!] organizationIds: [ID!] priceGroupIds: [ID!] } "The product-scope input — ≥1 member (sane predicate, unique ids, included∩excluded refused); omit the field to match ALL product lines." input PromotionProductScopeInput { predicate: CollectionPredicateInput includedProductIds: [ID!] excludedProductIds: [ID!] collectionId: ID } "The cart-conditions input — ≥1 member with unique ids." input PromotionCartConditionsInput { minQty: Int minSubtotalMinor: Int requiredProductIds: [ID!] requiredCategoryIds: [ID!] } "Create-input for a Promotion. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; free_gift/free_shipping effects refuse by the NAMED deferral gate BEFORE the generic parse; every scope/conditions/effect ref is tenant-scoped server-side and must be ACTIVE; startAt stamps NOW when omitted; priority/exclusive/couponGated default 100/false/false." input NewPromotionInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Promotion'; when supplied it must be non-blank." caption: String effect: PromotionEffectInput! scope: PromotionScopeInput productScope: PromotionProductScopeInput cartConditions: PromotionCartConditionsInput "The window start (UTC ISO-8601) — omitted ⇒ stamped NOW; a FUTURE instant is the advance-scheduling arm." startAt: String "The window end (half-open) — omitted ⇒ evergreen; must lie strictly after the (stamped) start." endAt: String "Resolution ordinal 0..1000000 — omitted ⇒ 100." priority: Int "Omitted ⇒ false; TRUE refuses a combinableGroup (incoherent)." exclusive: Boolean combinableGroup: String maxDiscountPerLineMinor: Int maxDiscountPerOrderMinor: Int totalRedemptionsCap: Int "Omitted ⇒ false; TRUE = fires ONLY through an attached trigger Coupon." couponGated: Boolean code: String } "Edit-input for a Promotion. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic)." input EditPromotionInput { caption: String code: String "Wholesale replacement — the deferred kinds refuse the same NAMED gate." effect: PromotionEffectInput scope: PromotionScopeInput productScope: PromotionProductScopeInput cartConditions: PromotionCartConditionsInput startAt: String endAt: String priority: Int exclusive: Boolean combinableGroup: String maxDiscountPerLineMinor: Int maxDiscountPerOrderMinor: Int totalRedemptionsCap: Int couponGated: Boolean } "The canned flavors (SPEC_REGISTRY row 106 VERBATIM, generated from the contracts COUPON_FLAVORS SoT — anti-drift; IMMUTABLE at birth): trigger = the code UNLOCKS a couponGated Promotion (the reduction lives THERE, source=promo position 3); discount = the code CARRIES its own effect (source=coupon position 2 — BEFORE promotions; the one ratified cross-engine interaction: both coexist by default)." enum CouponFlavor { trigger discount } "The discount-flavor effect: kind ∈ {percent_off, amount_off} ONLY. percent_off reduces EACH matched line by the ppm on its position-2 running subtotal; amount_off is ONE order-wide figure allocated largest-remainder across the matched lines. minSubtotalMinor gates on the Σ matched running subtotal (a miss = VALIDATION/COUPON_INELIGIBLE); productScope narrows the matched lines (absent = all product lines)." type CouponEffect { kind: PromotionEffectType! percentPpm: Int amountMinor: Int minSubtotalMinor: Int productScope: PromotionProductScope } "A Coupon — the CODE-GATED entry to the discount engines: a normalized code (trim+UPPERCASE, stored normalized-only, IMMUTABLE at birth — re-code = a new coupon) that either UNLOCKS a couponGated Promotion (trigger flavor — the reduction is source=promo at position 3) or CARRIES its own simple effect (discount flavor — source=coupon at position 2, BEFORE promotions). Attach to an OPEN order via applyOrderCoupon (HARD 1 coupon/order — the strict default); redemption counts per ORDER in the place transaction — a capped-out coupon refuses CONFLICT/COUPON_EXHAUSTED. NAMED deferrals: CouponBatch (unique single-use child codes) · per-customer caps." type Coupon { id: ID! "The group-scoped human-facing system id (CP-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Coupon parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned flavor (SPEC_REGISTRY row 106) — IMMUTABLE at birth." flavor: CouponFlavor! "No further notes." code: String! "trigger flavor ONLY: the unlocked couponGated Promotion (same-tenant + ACTIVE at create) — IMMUTABLE (re-point = a new coupon)." promotionId: ID "discount flavor ONLY: the carried effect — wholesale-replace on edit (refused on trigger, the cross-flavor gate)." effect: CouponEffect "The half-open window start (kit-stamped NOW when omitted at create)." startAt: String! "The half-open window end — ABSENT = evergreen; out-of-window redemption refuses CONFLICT/COUPON_EXPIRED." endAt: String "Total-use cap." totalUsesCap: Int } "No further notes." input CouponEffectInput { kind: PromotionEffectType! percentPpm: Int amountMinor: Int minSubtotalMinor: Int productScope: PromotionProductScopeInput } "Create-input for a Coupon. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; the RAW code is normalized (trim+UPPERCASE) + grammar-gated server-side; flavor⟺payload coherence is the boundary refine (trigger ⟺ promotionId, discount ⟺ effect); a trigger promotion must be same-tenant + ACTIVE + couponGated." input NewCouponInput { "Optional: when omitted the per-type default applies — the NORMALIZED code (self-documenting — the code IS the identity); when supplied it must be non-blank." caption: String "The RAW code (1..64 pre-normalization) — normalized + grammar-gated server-side; the org-group ACTIVE-code UNIQ marker mints IN the create transaction (a LIVE holder refuses CONFLICT/COUPON_CODE_TAKEN naming it; a DOOMED holder is taken over)." code: String! flavor: CouponFlavor! "REQUIRED iff trigger: the unlocked Promotion (tenant-scoped + ACTIVE + couponGated — REF_STATE / VALIDATION/INVALID otherwise)." promotionId: ID "REQUIRED iff discount: the carried effect." effect: CouponEffectInput "The window start — omitted ⇒ stamped NOW." startAt: String "The window end (half-open) — omitted ⇒ evergreen." endAt: String totalUsesCap: Int } "Edit-input for a Coupon. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic)." input EditCouponInput { caption: String "discount flavor ONLY (VALIDATION/INVALID naming the field on trigger)." effect: CouponEffectInput startAt: String endAt: String totalUsesCap: Int } "The canned instrument types (SPEC_REGISTRY row 97 VERBATIM, generated from the contracts STORED_VALUE_INSTRUMENT_TYPES SoT — anti-drift; IMMUTABLE at birth): gift_card = purchasable + reloadable-by-field + bearer · gift_certificate = fixed-amount, never reloadable · store_credit = refund/goodwill-born, customer-BOUND, never purchasable as a line." enum StoredValueInstrumentType { gift_card gift_certificate store_credit } "The canned ledger reasons (SPEC_REGISTRY row 136 VERBATIM, generated from the contracts STORED_VALUE_ENTRY_TYPES SoT): issue/reload/refund_reversal load value ON; redeem/expire draw value OFF; adjust/transfer are signed either way. expire/transfer have NO writer (registered-not-buildable — the /policy leg)." enum StoredValueEntryType { issue reload redeem refund_reversal adjust expire transfer } "ONE immutable stored-value balance fact: the signed amountMinor IS the balance direction; the parent instrument's balanceMinor was stamped in the SAME transaction. Corrections are NEW adjust entries, never edits." type StoredValueEntry { id: ID! "The parent StoredValueInstrument." parentId: ID! entryType: StoredValueEntryType! "The SIGNED minor-unit amount — the sign is the balance direction (issue/reload/refund_reversal +, redeem −, adjust either)." amountMinor: Int! currency: String! "The reason text — REQUIRED on adjust (the reason-coded stance), optional narration otherwise." reason: String "The driving Order." orderId: ID "The driving Tender (the redeem/refund_reversal arms)." tenderId: ID "The driving Return (the store-credit mint + original-tender reversal arms)." returnId: ID caption: String! createdAt: String! } "A StoredValueInstrument — a balance-bearing money instrument: gift_card (purchasable, reloadable-by-field, bearer) · gift_certificate (fixed-amount) · store_credit (refund/goodwill-born, customer-BOUND, never purchasable as a line). The FSM tracks USABILITY; the StoredValueEntry ledger tracks VALUE — balanceMinor is the cached ledger sum, stamped in the SAME transaction as every entry (the / law), with every decrement CONDITIONED (never negative — CONFLICT/INSUFFICIENT_BALANCE). Dual-birth: immediate active (the issue entry rides the create) or STAGED inactive printed stock (activated at sale via the Order line arm, or directly via activateStoredValueInstrument). Selling/reloading one is an Order LINE (untaxed — basis instrument_sale; engine-invisible); redeeming one is an applyTender step-5 internal tender; store credit from a return mints via refundReturn method=store_credit. Doom is gated by CONFLICT/BALANCE_OUTSTANDING while value remains (zero via reason-coded adjust FIRST — no silent money destruction)." type StoredValueInstrument { id: ID! "The group-scoped human-facing system id (SV-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | depleted | doomed." status: String! "The parent org group; for a StoredValueInstrument parentId === rootId (group-scoped — any org in the group redeems it)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned type (SPEC_REGISTRY row 97) — IMMUTABLE at birth." instrumentType: StoredValueInstrumentType! "The NORMALIZED code (trim+UPPERCASE; A–Z/0–9 start then A–Z/0–9/_/-, 4..64 — a money key needs collision room) — IMMUTABLE at birth; BURNED at doom." code: String! "The reload law: true ⟺ a reloadable gift_card; FORCED false on certificate/credit (strict both ways)." reloadable: Boolean! "The CACHED ledger sum (minor units) — stamped in the SAME transaction as every StoredValueEntry; NEVER negative; NEVER directly editable (adjust/redeem/reload are the only balance surfaces)." balanceMinor: Int! "The instrument currency — the issuing org default stamped at birth." currency: String! "The inline customer binding." customer: OrderCustomer } "One page of the storedValueInstruments listing — the records + the opaque resume cursor." type StoredValueInstrumentPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [StoredValueInstrument!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for the DIRECT instrument lanes. Dual-birth by initialBalanceMinor: PRESENT = immediate active (the issue entry rides the create transaction; reason REQUIRED — money is born); ABSENT = STAGED inactive stock (code REQUIRED — the plastic carries its number). The tenant is derived SERVER-SIDE; currency = the named issuing org's defaultCurrency (in-tenant + ACTIVE + a default set — the Order-create law); the RAW code normalizes + grammar-gates server-side and its org-group marker mints IN the transaction (ANY holder — doomed included — refuses CONFLICT/INSTRUMENT_CODE_TAKEN: the BURN law); store_credit requires the customer block and never stages." input NewStoredValueInstrumentInput { "Optional: when omitted the per-type default applies — the instrumentType + the NORMALIZED code; when supplied it must be non-blank." caption: String "The ISSUING org (in-tenant + ACTIVE) — its defaultCurrency stamps the instrument." organizationId: ID! instrumentType: StoredValueInstrumentType! "The RAW code (1..64 pre-normalization) — REQUIRED on the staged arm (printed stock carries its number); omitted on the immediate arm = system-minted." code: String "gift_card ONLY (default true there); REFUSED on certificate/credit (strict both ways)." reloadable: Boolean "PRESENT = immediate-active birth loading this value (the issue entry rides the transaction); ABSENT = staged inactive stock." initialBalanceMinor: Int "REQUIRED on store_credit; optional bearer-binding on gift instruments." customer: OrderCustomerInput "REQUIRED on the immediate-active arm (money is born; ≤ 256)." reason: String } "Edit-input for a StoredValueInstrument. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). instrumentType/code are IMMUTABLE at birth; balanceMinor NEVER edits (the ledger is the only balance surface — adjust/redeem/reload); reloadable edits on gift_card ONLY (the cross-type gate names the field over the CURRENT record)." input EditStoredValueInstrumentInput { caption: String "gift_card ONLY (VALIDATION/INVALID naming the field otherwise)." reloadable: Boolean "Replace the binding wholesale — a store_credit binding can be corrected, never cleared." customer: OrderCustomerInput } "A points↔currency rate pair: directional by field — the EARN rate reads \"earn points per perMinor of eligible spend\"; the REDEEM rate reads \"points convert to perMinor of discount value\". BigInt cross-multiply, floor ONCE." type LoyaltyRate { points: Int! perMinor: Int! } "ONE category/product earn-multiplier row: lines whose product matches earn at multiplierPercent (100 = 1×, 200 = 2×); multiple matching rows take the MAX (never stack)." type LoyaltyEarnMultiplier { predicate: CollectionPredicate! multiplierPercent: Int! } "ONE time-boxed bonus-earn window: half-open [startAt, endAt), BOTH bounds required; overlapping windows take the MAX." type LoyaltyBonusWindow { startAt: String! endAt: String! multiplierPercent: Int! } "ONE named tier: thresholdPoints is the qualification figure the future sweeper reads." type LoyaltyTier { name: String! thresholdPoints: Int! earnMultiplierPercent: Int! } "A LoyaltyProgram — the points engine's GROUP-scoped rule master: members EARN points on net merchandise spend (floor(base × earnRate.points ÷ earnRate.perMinor) — floor ONCE at the order level over the FINAL post-redemption discounted taxable bases, storedValue lines excluded) and REDEEM them as a PRE-TAX DISCOUNT at the step-2 position 4 (source=loyalty LINE entries — after manual → coupon → promotion; the taxonomy law: loyalty is a DISCOUNT, categorically NOT a tender — no loyalty tender type exists). currency is EXPLICIT + IMMUTABLE at birth (a group's orgs may differ in defaultCurrency — orders in another currency refuse the attach; FX = the deferral). Earn multipliers COMPOUND multiplicatively across three families — tier × active bonus window × MAX(matching predicate rows, never stacked) — each family ≤ 8 rows. Org participation is the canned-pool selection (organizationIds ABSENT = every org in the group). The effective window is half-open [startAt, endAt) — an EVALUATION gate, never FSM states. At most 8 ACTIVE per org group. Doom is -gated by non-doomed members (doom the members first); deactivate stays FREE. Tier ASSIGNMENT is a manual member edit v1 (the auto-evaluation sweeper is a NAMED deferral); points expiry/transfer, redemption caps, ecom/non-sale loyalty and fraud velocity are the NAMED deferrals." type LoyaltyProgram { id: ID! "The group-scoped human-facing system id (LP-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a LoyaltyProgram parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The program earn/redeem currency (ISO-4217) — EXPLICIT + IMMUTABLE at birth." currency: String! "Earn `points` per `perMinor` of eligible spend." earnRate: LoyaltyRate! "`points` convert to `perMinor` of pre-tax discount value." redeemRate: LoyaltyRate! "Category/product earn multipliers — matching lines take the MAX row (never stacked); compounds with tier × bonus." earnMultipliers: [LoyaltyEarnMultiplier!] "Time-boxed bonus-earn windows (≤ 8; BOTH bounds required, half-open) — overlapping windows take the MAX; a PROGRAM rule, deliberately NOT a promotion effect." bonusWindows: [LoyaltyBonusWindow!] "Named tiers (≤ 8; unique names) — config + benefit math ship v1; ASSIGNMENT is a manual member edit and auto-evaluation is the deferral." tiers: [LoyaltyTier!] "The canned-pool org selection — ABSENT = every org in the group participates." organizationIds: [ID!] "The half-open window start (UTC ISO-8601; kit-stamped NOW when omitted at create) — IMMUTABLE at birth (the history anchor)." startAt: String! "The half-open window end — ABSENT = evergreen; [startAt, endAt) is an EVALUATION gate." endAt: String } "One page of the loyaltyPrograms listing — the records + the opaque resume cursor." type LoyaltyProgramPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [LoyaltyProgram!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The LoyaltyRate input twin." input LoyaltyRateInput { points: Int! perMinor: Int! } "The LoyaltyEarnMultiplier input twin — the predicate must be sane." input LoyaltyEarnMultiplierInput { predicate: CollectionPredicateInput! multiplierPercent: Int! } "The LoyaltyBonusWindow input twin — startAt strictly before endAt." input LoyaltyBonusWindowInput { startAt: String! endAt: String! multiplierPercent: Int! } "The LoyaltyTier input twin — names unique within the array." input LoyaltyTierInput { name: String! thresholdPoints: Int! earnMultiplierPercent: Int! } "Create-input for a LoyaltyProgram. The tenant is derived SERVER-SIDE; currency is EXPLICIT + IMMUTABLE (ISO-4217, minor-unit-registered); startAt is kit-stamped NOW when omitted; the ACTIVE cap (≤ 8 per group) gates the create; rule arrays are each ≤ 8 rows with sane predicates and unique tier names." input NewLoyaltyProgramInput { "Optional: when omitted the per-type default applies — the phrase `loyalty program `; when supplied it must be non-blank." caption: String "IMMUTABLE at birth — the earn/redeem currency anchor." currency: String! earnRate: LoyaltyRateInput! redeemRate: LoyaltyRateInput! earnMultipliers: [LoyaltyEarnMultiplierInput!] bonusWindows: [LoyaltyBonusWindowInput!] tiers: [LoyaltyTierInput!] "The canned-pool selection — ABSENT = every org in the group." organizationIds: [ID!] "Omitted = kit-stamped NOW; IMMUTABLE once born." startAt: String "ABSENT = evergreen; must lie strictly after the window start." endAt: String } "Edit-input for a LoyaltyProgram. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). currency and startAt are IMMUTABLE at birth (the rate anchor + the history anchor); the RESULTING window must keep endAt strictly after the immutable startAt (the RC-h merged-edit law)." input EditLoyaltyProgramInput { caption: String earnRate: LoyaltyRateInput redeemRate: LoyaltyRateInput "Wholesale replace (the array-edit law)." earnMultipliers: [LoyaltyEarnMultiplierInput!] "Wholesale replace." bonusWindows: [LoyaltyBonusWindowInput!] "Wholesale replace — a renamed tier degrades assigned members to the base multiplier at evaluation (never a cart-killing throw)." tiers: [LoyaltyTierInput!] "Wholesale replace of the canned pool." organizationIds: [ID!] endAt: String } "The member's inline customer identity." type LoyaltyCustomer { name: String "REQUIRED — the enrollment identity key (stored trim+lowercase-NORMALIZED)." email: String! phone: String } "The canned points-ledger reasons (SPEC_REGISTRY row 137 + the ONE DISCLOSED additive amendment redeem_reversal — generated from the contracts LOYALTY_POINTS_ENTRY_TYPES SoT): earn/redeem_reversal load points ON; redeem/clawback/expire draw points OFF; adjust/transfer are signed either way. expire/transfer have NO writer (registered-not-buildable — the /policy leg)." enum LoyaltyPointsEntryType { earn redeem redeem_reversal adjust expire clawback transfer } "ONE per-line points share on an order/return-driven entry: the return-side clawback/restore arithmetic is EXACT per returned line, no pro-rata drift under multipliers." type LoyaltyEntryLineDetail { lineNo: Int! points: Int! } "ONE immutable points fact: the SIGNED points figure IS the balance direction; the parent member's pointsBalance was stamped in the SAME transaction. Corrections are NEW adjust entries, never edits." type LoyaltyPointsEntry { id: ID! "The parent LoyaltyMember." parentId: ID! entryType: LoyaltyPointsEntryType! "The SIGNED points figure — the sign is the balance direction (earn/redeem_reversal +, redeem/clawback/expire −, adjust either)." points: Int! "The reason text — REQUIRED on adjust (the reason-coded stance), optional narration otherwise." reason: String "The driving Order." orderId: ID "The driving Return (the return clawback/restore arms; return-driven entries carry BOTH refs)." returnId: ID "The per-line split." lines: [LoyaltyEntryLineDetail!] caption: String! createdAt: String! } "A LoyaltyMember — ONE enrollment of ONE customer identity into ONE LoyaltyProgram (parentId = the program). Enrollment REQUIRES identity: the inline customer block with email REQUIRED (trim+lowercase-normalized — anonymous/walk-in cannot earn); the (program × normalized email) UNIQ marker reserves IN the create transaction — a LIVE holder refuses CONFLICT/MEMBER_EXISTS naming the holder (the email is never echoed), while a DOOMED member's identity RE-ENROLLS fresh (an identity is not a bearer money key — the explicit contrast with the instrument-code BURN). pointsBalance is the CACHED LoyaltyPointsEntry ledger sum (PK=LOYLEDGER#), stamped in the SAME transaction as every entry (the / law), with every draw CONDITIONED balance ≥ draw — points NEVER go negative (CONFLICT/INSUFFICIENT_POINTS names live figures) and cap at 1000000000. Earn/redeem ride the Order PLACE transaction; cancel claws back IN the cancel transaction (spent-below-earned REFUSES the cancel); returns claw earn + restore redemption EXACTLY off the entries' per-line details in the refund flip transaction. adjustLoyaltyPoints is the ONLY manual points surface. Doom is gated by CONFLICT/BALANCE_OUTSTANDING while points remain (zero via reason-coded adjust FIRST); tier assignment is a manual edit v1." type LoyaltyMember { id: ID! "The group-scoped human-facing system id (LM-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent LoyaltyProgram — NOT the family root; rootId anchors the org group." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The enrollment identity." customer: LoyaltyCustomer! "The CACHED ledger sum — stamped in the SAME transaction as every LoyaltyPointsEntry; NEVER negative; NEVER directly editable (adjust/earn/redeem are the only points surfaces)." pointsBalance: Int! "The assigned tier NAME (v1 manual assignment via update; must name a program tier at write time; a later program rename degrades to the base multiplier at evaluation)." currentTier: String "The assigned CustomerPriceGroup. / bind groups per their locks; the Consumer binding SUPERSEDES." priceGroupId: ID "The Consumer identity bridge. The coherence gate rides it: an order naming BOTH a member and a consumer refuses when this bridge points at a DIFFERENT consumer; a consumer-named order resolves pricing from the CONSUMER binding — this member carrier stands only on member-named-without-consumer orders." consumerId: ID } "One page of the loyaltyMembers listing — the records + the opaque resume cursor." type LoyaltyMemberPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [LoyaltyMember!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The LoyaltyCustomer input twin." input LoyaltyCustomerInput { name: String email: String! phone: String } "ENROLL-input for a LoyaltyMember. The tenant is derived SERVER-SIDE; the program gates in-tenant + ACTIVE; the email normalizes (trim+lowercase) and its (program × email) marker mints IN the transaction (a LIVE holder refuses CONFLICT/MEMBER_EXISTS; a DOOMED holder is taken over — re-enrollable); pointsBalance births 0; an initial tier must name a program tier." input NewLoyaltyMemberInput { "Optional: when omitted the per-type default applies — the phrase `member `; when supplied it must be non-blank." caption: String "The LoyaltyProgram to enroll into — in-tenant + ACTIVE." programId: ID! "The identity block — email REQUIRED (the enrollment identity; normalized server-side)." customer: LoyaltyCustomerInput! "Optional initial tier NAME — must name a program tier." currentTier: String "Optional CustomerPriceGroup assignment." priceGroupId: ID "Optional Consumer bridge." consumerId: ID } "Edit-input for a LoyaltyMember. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). An email change MIGRATES the (program × email) identity marker atomically with the update (people change emails — ≠ the immutable coupon/instrument codes); the new email held by ANY member — doomed included — refuses CONFLICT/MEMBER_EXISTS (an edit admits NO takeover; a doomed holder's identity re-enters via ENROLL). currentTier must name a program tier (≤ 60 chars); pointsBalance NEVER edits (the ledger is the only points surface)." input EditLoyaltyMemberInput { caption: String "Replace the identity wholesale — an email change migrates the UNIQ marker atomically." customer: LoyaltyCustomerInput "The v1 manual tier assignment." currentTier: String "Re-assign the CustomerPriceGroup." priceGroupId: ID "Set/re-point the Consumer bridge." consumerId: ID } "A CustomerPriceGroup — the customer-classification / pricing-ELIGIBILITY axis (retail tiers: standard · member · vip · wholesale_lite — merchant-defined, the registry's roster is illustrative). An eligibility KEY, NOT a price store: the group carries NO rate fields — its benefits are expressed EXCLUSIVELY promotions scoped to it (PromotionScope.priceGroupIds); the priceListId CARRIER is live while the group itself stays rate-field-FREE (the anti-price-plane guard's letter: the PLANE is the PriceList's, the group is the eligibility KEY + the carrier). The axis law: CustomerPriceGroup = pricing eligibility · Segment = marketing audience · CorporateCustomer = B2B identity — three distinct axes a customer may carry independently. Assignment v1 rides the LoyaltyMember carrier (member.priceGroupId, the PRE- home; OrgCustomer and Consumer bind per their locks, the Consumer binding SUPERSEDES). Resolution DEGRADES: anonymous / no member / no group / group non-ACTIVE-or-deselected ⇒ no eligibility — a lapsed group NEVER kills a cart. Org participation is the canned-pool selection (≤ 32; ABSENT = every org). At most 32 ACTIVE per org group. Doom is -gated by non-doomed LoyaltyMembers carrying the group; deactivate stays FREE (a paused group's scoped promotions simply stop matching). NO code/identity — no UNIQ marker (nothing bearer-resolvable rides a group)." type CustomerPriceGroup { id: ID! "The group-scoped human-facing system id (PG-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a CustomerPriceGroup parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned-pool org selection — ABSENT = every org in the group participates." organizationIds: [ID!] "The group-base-pricing carrier: an UNSCOPED PriceList whose entries feed the GROUP plane at capture. Gated in-tenant + ACTIVE + UNSCOPED at set (a contract list on a tier would leak one customer's negotiated prices — CONFLICT/REF_STATE naming the scope). Optional + editable; a list dying later DEGRADES at capture." priceListId: ID } "One page of the customerPriceGroups listing — the records + the opaque resume cursor." type CustomerPriceGroupPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CustomerPriceGroup!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a CustomerPriceGroup. The tenant is derived SERVER-SIDE; ⚠ the caption IS the tier name and is REQUIRED at the boundary (the divergence from the optional-caption convention — an unnamed eligibility tier is meaningless; omission refuses VALIDATION/INVALID); the ACTIVE cap (≤ 32 per group) gates the create; priceListId gates in-tenant + ACTIVE + UNSCOPED. Deliberately rate-field-FREE (the anti-price-plane guard — benefits ride group-scoped promotions; the PLANE rides the carried PriceList)." input NewCustomerPriceGroupInput { "Optional: when omitted the per-type default applies — NONE — the divergence: the caption IS the tier name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The canned-pool selection — ABSENT = every org in the group." organizationIds: [ID!] "The group-base-pricing carrier." priceListId: ID } "Edit-input for a CustomerPriceGroup. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic)." input EditCustomerPriceGroupInput { "The tier name." caption: String "Wholesale replace of the canned pool." organizationIds: [ID!] "The carrier." priceListId: ID } "The canned step-move kinds (SPEC_REGISTRY row 110 VERBATIM)." enum MarkdownMoveKind { percent_off amount_off to_fixed } "One cadence step — the stored twin of MarkdownStepInput." type MarkdownStep { startAt: String! move: MarkdownMove! endAt: String } "One step's MOVE — kind + the matching branch field (the discriminated union flattened for the wire)." type MarkdownMove { kind: MarkdownMoveKind! percentPpm: Int amount: MoneyEntry } "A MarkdownPlan — the markdown CADENCE: a product scope (the grammar VERBATIM — predicate + inclusions/exclusions + a Collection ref) + ≤ 8 ordered effective-dated steps (percent_off ppm-EXCLUSIVE · amount_off · to_fixed; startAt strictly increasing; the LAST step MAY carry endAt = the clearance-LAPSE arm, absent = the standing far-future window). the write rule: the schedule transition pre-computes the whole price LADDER per targeted InventoryItem (base₀ = the record covering step-1's startAt, then each PRIOR RESULT — half-away rounding, every result > 0) and WRITES EVERY future-dated SalePrice up-front through the existing per-record create (splice-gated, evented, plan/step-stamped; the FIRST window per II TRIMS the covering standing record; caps: ≤ 250 items · ≤ 500 writes). The prices then move by dated-window resolution ALONE — the scheduler fires ONLY the plan's own status flips (scheduled→active at the first step's moment · active→completed after the last; a down sweeper delays ZERO price moves — the flips are observability). The live splice law PROTECTS the cadence (an external overlapping write refuses CONFLICT/PRICE_WINDOW_OVERLAP naming the plan's records). Cancel dooms the not-yet-effective plan-stamped records ONLY (effective windows are permanent price history; the step-1 trim is NOT restored). A markdown MOVES the step-1 base — promotions/loyalty/employee compose on top UNCHANGED. Update is DRAFT-only (amend-after-schedule = cancel + author anew). At most 32 OPEN (draft+scheduled+active) per org group. Org participation is the canned-pool selection (≤ 32; ABSENT = every org); logicalFacilityIds (≤ 32) RESTRICTS within the selected orgs' facilities (ABSENT = all of them). NOT searchable (the document non-joiner stance — this born-paginated list is the discovery read); NO UNIQ marker." type MarkdownPlan { id: ID! "The group-scoped human-facing system id (MD-…)." sysId: String! type: String! caption: String! "The FSM state: draft | scheduled | active | completed | cancelled." status: String! "The parent org group; for a MarkdownPlan parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "WHAT the cadence re-prices. REQUIRED with ≥1 member — an absent markdown scope would read 'reprice the whole catalog' (the anti-sitewide divergence from promotions)." productScope: PromotionProductScope! "The canned-pool org selection — ABSENT = every org in the group participates." organizationIds: [ID!] "The explicit LF restriction — ABSENT = all LFs of the selected orgs." logicalFacilityIds: [ID!] "The plan currency — every scoped II's schedule currency must EQUAL it at schedule time, and every money-bearing move carries it." currency: String! "The ordered cadence (1–8 steps): startAt strictly increasing, ALL future at schedule time; intermediate windows CHAIN to the next step's startAt; the LAST window ends at its explicit endAt (the lapse arm) or the standing 9999-12-31T00:00:00.000Z." steps: [MarkdownStep!]! "SYSTEM-maintained: schedule stamps steps[0].startAt; the activate firing re-stamps steps[last].startAt; terminal statuses disarm the lane." nextDueAt: String "SYSTEM-stamped at schedule: the resolved fan-out targets — the cancel doom-walk's bounded custody." resolvedInventoryItemIds: [ID!] } "One page of the markdownPlans listing — the records + the opaque resume cursor." type MarkdownPlanPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [MarkdownPlan!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "One cadence step: an effective instant + a move. endAt is legal on the LAST step ONLY (the clearance-LAPSE arm); intermediate windows CHAIN to the next step's startAt." input MarkdownStepInput { "The step's effective instant (UTC ISO-8601) — strictly increasing across the plan; ALL future at schedule time." startAt: String! move: MarkdownMoveInput! "LAST step only: the explicit window end (strictly after its own startAt) = the clearance-LAPSE arm; ABSENT = the standing far-future window." endAt: String } "One step's MOVE: percent_off carries percentPpm (EXCLUSIVE (0, 1000000) — a 100% move is not a price); amount_off/to_fixed carry amount (the plan currency). Exactly the matching branch field must be supplied — the boundary refuses mismatches." input MarkdownMoveInput { kind: MarkdownMoveKind! "percent_off ONLY: parts-per-million off the LADDER price." percentPpm: Int "amount_off/to_fixed ONLY: the money figure (must carry the plan currency)." amount: MoneyEntryInput } "Create-input for a MarkdownPlan. The tenant is derived SERVER-SIDE; ⚠ the caption is REQUIRED at the boundary (the CustomerPriceGroup divergence class — a cadence has no natural default; omission refuses VALIDATION/INVALID); the OPEN bound gates the create kit-side. The all-future/base/splice/cap gates are the SCHEDULE transition's — a draft may be authored ahead of its own validity." input NewMarkdownPlanInput { "Optional: when omitted the per-type default applies — NONE — the divergence: a cadence has no natural default name, so an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The scope — REQUIRED with ≥1 member." productScope: PromotionProductScopeInput! "The canned-pool selection — ABSENT = every org in the group." organizationIds: [ID!] "The explicit LF restriction — ABSENT = all LFs of the selected orgs." logicalFacilityIds: [ID!] "The plan currency (ISO-4217) — every money-bearing move must carry it." currency: String! "1–8 ordered steps — startAt strictly increasing; endAt on the LAST step only." steps: [MarkdownStepInput!]! } "Edit-input for a MarkdownPlan. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). DRAFT-ONLY: a scheduled/active plan refuses CONFLICT/REF_STATE naming the status (amend-after-schedule = cancel + author anew); terminals refuse CONFLICT/IMMUTABLE. The currency⇄moves law re-asserts on the MERGED plan (either half may arrive alone)." input EditMarkdownPlanInput { "The plan name." caption: String "Wholesale replace of the scope." productScope: PromotionProductScopeInput "Wholesale replace of the canned pool." organizationIds: [ID!] "Wholesale replace of the LF restriction." logicalFacilityIds: [ID!] "The plan currency — re-asserted against the (merged) steps." currency: String "Wholesale replace of the cadence." steps: [MarkdownStepInput!] } "The canned commission rate types (SPEC_REGISTRY row 100 VERBATIM)." enum CommissionRateType { percent_net percent_margin fixed_per_unit } "The commission earning formula: percent_net/percent_margin carry valuePpm (INCLUSIVE (0, 1000000]); fixed_per_unit carries amount (per unit, scale-4 quantity arithmetic; a currency-mismatched fixed rate is NON-matching for the line)." type CommissionRate { type: CommissionRateType! valuePpm: Int amount: MoneyEntry } "The canned commission-ledger reasons: earn (+, minted at PLACE) · clawback (−, the cancel/return reversal). NO adjust arm v1 (reports-only — a mis-configured rate is fixed FORWARD on the config)." enum CommissionEntryType { earn clawback } "The entry classes: attributed = the line-slot splits · manager_on_all = the flagged-config holder additive (a manager who ALSO rang the sale earns BOTH — separate entries; a claw reverses per class)." enum CommissionEntryClass { attributed manager_on_all } "ONE per-line commission share." type CommissionEntryLineDetail { lineNo: Int! basisMinor: Int! splitWeightPpm: Int amountMinor: Int! } "ONE immutable commission fact: the SIGNED minor-unit figure IS the payable direction; ONE entry per (agent × class × winning config × order). Corrections are NEW clawback entries, never edits; the configId is immutable provenance (history outlives a doomed config)." type CommissionEntry { id: ID! "The parent AGENT (a User) — rows ride COMMLEDGER#." parentId: ID! entryType: CommissionEntryType! entryClass: CommissionEntryClass! "The SIGNED payable figure (minor units — earn +, clawback −)." amountMinor: Int! currency: String! "The winning config." configId: ID "The driving Order." orderId: ID! "The driving Return (the return-clawback arm; return-driven entries carry BOTH refs)." returnId: ID "The per-line split." lines: [CommissionEntryLineDetail!] caption: String! createdAt: String! } "One commissionEntryList page." type CommissionEntryPage { items: [CommissionEntry!]! "Resume cursor — ABSENT on the last page (pass back verbatim as nextToken)." nextToken: String } "One payout-report row: the signed Σ per (subject × currency) over entries createdAt ∈ [from, to); late claws land in THEIR OWN period as negative rows." type CommissionPayoutRow { "The agent User (commission report) or the Affiliate (affiliate report) the row aggregates." subjectId: ID! currency: String! earnedMinor: Int! clawedBackMinor: Int! "earnedMinor − clawedBackMinor — the signed payable." payableMinor: Int! entryCount: Int! } "One payout-report page." type CommissionPayoutRowPage { items: [CommissionPayoutRow!]! nextToken: String } "A CommissionConfig — ONE cell of the multi-axis commission matrix (the ReplenishmentConfig SIBLING): the AXES scope WHERE it applies (each SINGULAR, absent = all, IMMUTABLE at birth — re-target = create + doom): Agent (a Role the agent holds at the sale's org ⊕ a specific User) · Merchandise (Division ⊕ Category-SUBTREE ⊕ Style — a style outranks any category depth) · Location (Organization ⊕ LogicalFacility — **the Location axis IS the org scoping; this construct is NOT org-selected**) · Channel. The SPARSE parameters (≥1 required): rate (percent_net = the line's FINAL post-position-5 discounted net · percent_margin = max(net − landed COGS, 0), COGS-absent ⇒ 0 · fixed_per_unit — a currency-mismatched fixed rate is NON-matching) + enabled (false at the winning cell SUPPRESSES the entry). At PLACE, per (line × attributed agent): candidates = ACTIVE cells matching EVERY axis; the winner PER PARAMETER is the most specific (set-axis count, tie-break Agent ≻ Merchandise ≻ Location ≻ Channel). appliesToAllSalesInScope=true + Agent=Role is the manager-on-all override: EVERY active holder of the Role at the sale's org earns additively (entryClass manager_on_all; bounded ≤ 32 holders — the write refuses over, the place mint SKIPS over [the sale never blocks]). the collision rule: an ACTIVE same-normalized-tuple sibling with an intersecting SET-parameter set refuses CONFLICT/IDENTITY_TAKEN naming the holder(s) + the intersection (create, param-GROWING edits, reactivate; same-tuple DISJOINT-parameter cells are LEGAL — the flag rides IN the tuple, so flagged/unflagged never compete). At most 128 ACTIVE per org group (the per-place resolution bound). NOT searchable (the config non-joiner stance — configs are axis-addressed, not name-found); NO UNIQ marker." type CommissionConfig { id: ID! "The group-scoped human-facing system id (CG-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a CommissionConfig parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The manager-on-all flag: every active holder earns on every in-scope line, additively." appliesToAllSalesInScope: Boolean "Agent axis (Role arm — roles are per-organization: matches agents holding it at the SALE’s org). SINGULAR with agentUserId; absent both = all agents." agentRoleId: ID "Agent axis (User arm — the most specific agent level). SINGULAR with agentRoleId." agentUserId: ID "Merchandise axis (Division arm). SINGULAR with categoryId/styleId; absent all three = all merchandise." divisionId: ID "Merchandise axis (Category arm — SUBTREE semantics; deeper beats shallower)." categoryId: ID "Merchandise axis (Style arm — the per-style override; outranks ANY category depth)." styleId: ID "Location axis (Organization arm) — THE org scoping. SINGULAR with logicalFacilityId." organizationId: ID "Location axis (LogicalFacility arm — the most specific location level)." logicalFacilityId: ID "Channel axis — the LIVE selling channels; absent = both." channel: OrderChannel "The earning formula (SPARSE — the most-specific SET cell wins the parameter; unresolved anywhere = NO entry, commission is config-opt-in)." rate: CommissionRate "The per-cell master switch (SPARSE) — false at the winning cell suppresses the entry." enabled: Boolean } "One page of the commissionConfigs listing — the records + the opaque resume cursor." type CommissionConfigPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CommissionConfig!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The commission rate input — exactly the matching branch field must be supplied." input CommissionRateInput { type: CommissionRateType! valuePpm: Int amount: MoneyEntryInput } "Create-input for a CommissionConfig." input NewCommissionConfigInput { "Optional: when omitted the per-type default applies — a readable axis summary (the class — e.g. `Commission: role …, category …, pos`); when supplied it must be non-blank." caption: String "The manager-on-all flag — literal true; REQUIRES agentRoleId (without agentUserId)." appliesToAllSalesInScope: Boolean "Agent axis (Role arm)." agentRoleId: ID "Agent axis (User arm)." agentUserId: ID "Merchandise axis (Division arm)." divisionId: ID "Merchandise axis (Category arm — subtree)." categoryId: ID "Merchandise axis (Style arm)." styleId: ID "Location axis (Organization arm)." organizationId: ID "Location axis (LogicalFacility arm)." logicalFacilityId: ID "Channel axis." channel: OrderChannel "The earning formula (≥1 of rate/enabled required — the substance rule)." rate: CommissionRateInput "The per-cell switch." enabled: Boolean } "Edit-input for a CommissionConfig. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). PARAMS-ONLY: a param-GROWING edit re-runs the tuple-collision gate over the MERGED set; the manager-holder bound re-asserts." input EditCommissionConfigInput { "The cell name." caption: String "The earning formula (a GROWING edit re-runs the collision gate)." rate: CommissionRateInput "The per-cell switch." enabled: Boolean } "One referral code: the NORMALIZED code + the optional INFORMATIONAL coupon link (the discount rides the coupon machinery independently — a dead coupon never breaks attribution)." type AffiliateCode { code: String! couponId: ID } "The canned affiliate-ledger reasons: earn (+, ONE per placed attributed order) · clawback (−, the cancel/return reversal)." enum AffiliateEntryType { earn clawback } "ONE immutable affiliate fact: ORDER-level (no per-line detail v1 — the product-scope predicate is a named deferral); basisMinor + ratePpm stamp the earn (self-auditing — the affiliate's rate is EDITABLE, the entry's snapshot is not)." type AffiliateEntry { id: ID! "The parent Affiliate — rows ride AFFLEDGER#." parentId: ID! entryType: AffiliateEntryType! "The SIGNED payable figure (minor units — earn +, clawback −)." amountMinor: Int! currency: String! "The ORDER NET the earn computed on (stamped on earn — self-auditing arithmetic)." basisMinor: Int "The rate snapshot (ppm — stamped on earn)." ratePpm: Int orderId: ID! returnId: ID caption: String! createdAt: String! } "One affiliateEntryList page." type AffiliateEntryPage { items: [AffiliateEntry!]! nextToken: String } "An Affiliate — the MERCHANT's affiliate/influencer promoter, rewarded for driving retail sales (≠ the platform affiliate, 's note). Org participation is the canned-pool selection (≤ 32; ABSENT = every org). The referral and coupon namespaces are INDEPENDENT: couponId is an INFORMATIONAL link (validated live, same-group) — registering the SAME string in both, linked, is the influencer pattern (use CODE for 10% off — the coupon discounts, the referral attributes). Cancel claws in full; returns claw pro-rata with the cumulative floor (the arm class); payouts are PERIOD reports. SEARCHABLE (the merchant-curated book is name-found — the law); at most 128 ACTIVE per group." type Affiliate { id: ID! "The group-scoped human-facing system id (AF-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for an Affiliate parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned-pool org selection — ABSENT = every org in the group participates." organizationIds: [ID!] "The owned referral codes (≤ 8; stored NORMALIZED; each marker-reserved). ABSENT/empty = a code-less (idle) affiliate — legal." codes: [AffiliateCode!] "The flat earning rate (ppm of ORDER NET, (0, 1000000]). ABSENT = tracking-only (attribution stamps, NO entries)." ratePpm: Int "The shopper link. OPTIONAL — a link, never an identity merge; flows byte-for-byte unchanged." consumerId: ID "The public influencer handle (trimmed 1..64). ⚠ NOT unique." handle: String "The influencer bio (trimmed ≤2000)." bio: String "The social profile links (≤8 trimmed url-ish strings; wholesale-replace on edit — the codes-array class)." socialLinks: [String!] "The self-reported audience figure (≥0 — informational; verification)." audienceSize: Int "The content-niche descriptors (≤16 plain bounded strings — NOT Tag refs, ruling; wholesale-replace)." nicheTags: [String!] } "One page of the affiliates listing — the records + the opaque resume cursor." type AffiliatePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Affiliate!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One referral code — normalized (trim + UPPERCASE) server-side; ≤ 64 chars pre-normalization; the strict post-normalization grammar refuses non-printable/spaced codes." input AffiliateCodeInput { code: String! couponId: ID } "Create-input for an Affiliate. The tenant is derived SERVER-SIDE; ⚠ the caption is REQUIRED at the boundary (an external promoter has no derivable name); codes normalize + grammar-gate + reserve their markers IN the create transaction; each couponId resolves live same-group; the ACTIVE bound gates kit-side." input NewAffiliateInput { "Optional: when omitted the per-type default applies — NONE — the divergence: an external promoter has no derivable default name, so an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The canned-pool selection — ABSENT = every org in the group." organizationIds: [ID!] "≤ 8 referral codes — normalized server-side; unique in-affiliate post-normalization; each reserves the org-group marker (CONFLICT/REFERRAL_CODE_TAKEN names a live holder)." codes: [AffiliateCodeInput!] "The flat order-net rate (ppm) — ABSENT = tracking-only." ratePpm: Int "The shopper link — live-gated (in-tenant + NOT-doomed Consumer)." consumerId: ID "The public handle (1..64; NOT unique — ruling)." handle: String "≤2000." bio: String "≤8 url-ish strings." socialLinks: [String!] "≥0 (informational)." audienceSize: Int "≤16 plain strings (NOT Tag refs)." nicheTags: [String!] } "Edit-input for a Affiliate. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic) — EXCEPT codes: a supplied codes list REPLACES WHOLESALE." input EditAffiliateInput { "The promoter name." caption: String "Wholesale replace of the canned pool." organizationIds: [ID!] "WHOLESALE replacement — the marker MIGRATE (empty array = release all)." codes: [AffiliateCodeInput!] "The flat order-net rate (ppm)." ratePpm: Int "The shopper link — live-gated at set." consumerId: ID handle: String bio: String "Wholesale replace." socialLinks: [String!] audienceSize: Int "Wholesale replace." nicheTags: [String!] } "A CorporateCustomer — WHO the merchant SELLS TO on business terms: the shared B2B customer MASTER, the sell-side mirror of the Vendor supplier master. Group-parented + deliberately thin (caption = the trading name · legalName · taxId · code): contact data + buyers ride the Contact/ContactAssignment family (a CorporateCustomer is an assignment HOST — buyers are purchasing-buyer-role assignments); the org-specific commercial payload (terms · credit · price group · addresses) IS the OrgCustomer relationship (an active OrgCustomer = the B2B selling enablement — the OrgVendor mirror). SEARCHABLE (a customer book you can't search by name fails its purpose — the law). Doom is blocked by NON-doomed OrgCustomer selections and LIVE hosted ContactAssignments; open ORDERS naming the customer never block — order refs re-validate FRESH at place. NOT an identity class (buyer auth/portal is); the customer hierarchy (parent company) is a NAMED deferral." type CorporateCustomer { id: ID! "The group-scoped human-facing system id (CU-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a CorporateCustomer parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The registered legal name; optional + editable." legalName: String "The business tax identifier — a plain bounded string; jurisdictional format validation is deliberately later. Optional + editable." taxId: String "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the corporateCustomers listing — the records + the opaque resume cursor." type CorporateCustomerPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CorporateCustomer!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for a CorporateCustomer. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here." input NewCorporateCustomerInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Corporate Customer'; when supplied it must be non-blank." caption: String legalName: String taxId: String code: String } "Edit-input for a CorporateCustomer. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic yet)." input EditCorporateCustomerInput { caption: String legalName: String taxId: String code: String } "The canned AR movement kinds: charge (+, the on_account tender + the DebitNote settle) · payment (−, arPay) · credit_memo (−, the Return original-tender arms + the CreditNote settle) · writeoff (−, arWriteoff — bad debt, reason REQUIRED) · finance_charge (+, registered-not-buildable — the policy arm has NO writer yet)." enum ArEntryType { charge payment credit_memo writeoff finance_charge } "No further notes." type ArEntry { id: ID! "The parent OrgCustomer (the house account — rows ride ARLEDGER#)." parentId: ID! entryType: ArEntryType! "The SIGNED debt movement (minor units — charge +, payment/credit_memo/writeoff −)." amountMinor: Int! "Always the enablement's arCurrency (the single-lane law)." currency: String! "When this debt falls due — REQUIRED on charge/finance_charge (stamped at post from the enablement's paymentTerms: net variants = post + 30 days), ABSENT on reducing kinds (the aging coordinate rides charges only)." dueAt: String "REQUIRED on writeoff (bad debt always says why); optional narration otherwise (a cheque reference)." reason: String "The driving Order." orderId: ID "The driving Tender (the charge + refund-reversal arms)." tenderId: ID "The driving Return (the original-tender credit_memo arm)." returnId: ID "The settled CreditNote (the AR lane)." creditNoteId: ID "The settled DebitNote (the AR lane)." debitNoteId: ID caption: String! createdAt: String! } "One arLedger page." type ArEntryPage { items: [ArEntry!]! "Resume cursor — ABSENT on the last page (pass back verbatim as nextToken)." nextToken: String } "One arAging bucket row." type ArAgingBucket { "The bucket token (the AR_AGING_BUCKETS roster)." bucket: String! "OPEN charges landing in this bucket (the frontier head counts at its cached partial)." count: Int! "Σ outstanding minor units in this bucket." totalMinor: Int! } "The arAging report." type ArAgingReport { orgCustomerId: ID! "The report instant (server-stamped UTC ISO-8601 — the raw-UTC day-math anchor)." asOf: String! "The enablement's AR currency — ABSENT when no AR history exists." arCurrency: String "The cached balance (Σ buckets == this — the two-way derivation)." arBalanceMinor: Int! "The 5 fixed buckets, roster order (zero rows INCLUDED — a report row is a coordinate, not a fact)." buckets: [ArAgingBucket!]! } "An OrgCustomer — the per-org selling ENABLEMENT of a group CorporateCustomer, the sell-side mirror of the OrgVendor: an ACTIVE OrgCustomer IS the B2B selling enablement (no B2B terms without one). Parent = the ORGANIZATION (not the family root); the selection IS the (org × corporateCustomer) edge — ≤1 live per pair via the UNIQ pair marker minted IN the create transaction. Terms payload: accountNumber · canned paymentTerms (the registry SHARED with the OrgVendor; NO free-text twin — a born construct starts canned-only) · creditLimit/orderMinimum house Money on the sell-side currency rule (NO local currency field — every money field matches the org's defaultCurrency at set, create AND edit; the OrgVendor's local purchasingCurrency is deliberately NOT mirrored; ENFORCEMENT is credit / minimums) · the customerPriceGroupId carrier (in-tenant + ACTIVE at set — the member-carrier class; the order-time B2B precedence law is; the CPG doom RI gains this SECOND carrier class) · billToContactId/shipToContactId (non-doomed + a LIVE ContactAssignment on THIS customer's host — sell-side counterparty addresses need host-membership integrity, the disclosed OrgVendor divergence). Deactivate FREE (selling paused); doom structurally unblocked EXCEPT live holder ExemptionCertificates. The priceListId carrier is LIVE. MOQ/case enforcement is." type OrgCustomer { id: ID! "The group-scoped human-facing system id (EC-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for an OrgCustomer parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group CorporateCustomer — set at creation, IMMUTABLE thereafter." corporateCustomerId: ID! "Our account/reference number in THE CUSTOMER'S AP system; optional + editable." accountNumber: String "The canned payment terms; a non-canned token is VALIDATION/INVALID. NO free-text twin. Optional + editable." paymentTerms: String "The credit limit. House Money on the sell-side currency law: must match the org's defaultCurrency at set (NO local currency field). Optional + editable." creditLimit: MoneyEntry "The order minimum. Same currency law. Optional + editable." orderMinimum: MoneyEntry "The CustomerPriceGroup carrier. Optional + editable." customerPriceGroupId: ID "The PriceList carrier: the CONTRACT plane feed — a cc-named order resolves its step-1 base from THIS list FIRST (ContractPrice ≻ group list ≻ SalePrice). Gated in-tenant + ACTIVE at set; a SCOPED (contract) list must name THIS OrgCustomer (CONFLICT/REF_STATE naming the scope holder). Optional + editable; a list dying later DEGRADES at capture." priceListId: ID "The default bill-to Contact — non-doomed + a LIVE assignment on THIS customer's host (ANY role). Optional + editable." billToContactId: ID "The default ship-to Contact — the same host-membership gate. Optional + editable." shipToContactId: ID "Optional mutable merchant reference code; uniqueness NOT enforced." code: String "The CACHED AR ledger sum in minor units. SYSTEM-maintained: READ-only, REFUSED on input (the commissionAgentUserIds custody class — the New/Edit inputs exclude it BY SHAPE). Absent ⇒ 0, no AR history yet." arBalanceMinor: Int "The AR currency — SYSTEM-stamped at the FIRST AREntry, IMMUTABLE thereafter: every subsequent AR act gates against it, so an org defaultCurrency flip can never blend the cache (multi-currency AR = the named deferral). READ-only, REFUSED on input." arCurrency: String } "One page of the orgCustomers listing — the records + the opaque resume cursor." type OrgCustomerPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgCustomer!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for an OrgCustomer. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and corporateCustomerId are tenant-scoped server-side and must be active (STRICT); ≤1 live selection per (org × cc) via the pair marker (CONFLICT/IDENTITY_TAKEN names a live holder; a doomed one is taken over). Every terms field is optional (the enablement stays creatable thin); creditLimit/orderMinimum must match the org's defaultCurrency (an org with NO defaultCurrency cannot store OrgCustomer money — CONFLICT/REF_STATE naming the absence, the order-create precedent); customerPriceGroupId gates in-tenant + ACTIVE; priceListId gates in-tenant + ACTIVE + the scope law (a scoped list must name THIS OrgCustomer); billTo/shipTo gate non-doomed + host-membership. ⚠ the AR custody fields (arBalanceMinor/arCurrency) are SYSTEM-maintained and NOT creatable." input NewOrgCustomerInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Customer'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group CorporateCustomer this enablement names — immutable after birth." corporateCustomerId: ID! accountNumber: String "The canned payment-terms token (net-30 · 2-10-net-30 · cod · prepaid)." paymentTerms: String "Must match the org's defaultCurrency (the sell-side currency law)." creditLimit: MoneyEntryInput "Same currency law." orderMinimum: MoneyEntryInput customerPriceGroupId: ID "The contract/book carrier." priceListId: ID billToContactId: ID shipToContactId: ID code: String } "Edit-input for a OrgCustomer. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). corporateCustomerId is NOT editable (immutable at birth, the enablement IS the (org × cc) edge; re-pointing = recreate), nor is the parent-org ref (the header). The FULL terms payload is editable; the carrier/pointer gates re-run at each set; a supplied money field re-gates against the org's LIVE defaultCurrency (the sell-side currency law)." input EditOrgCustomerInput { caption: String code: String accountNumber: String "The canned payment-terms token (net-30 · 2-10-net-30 · cod · prepaid)." paymentTerms: String creditLimit: MoneyEntryInput orderMinimum: MoneyEntryInput customerPriceGroupId: ID "The contract/book carrier." priceListId: ID billToContactId: ID shipToContactId: ID } "A PriceList — a named ALTERNATE base-price plane (a 'price book'): the pipeline STEP-1 base for eligible customers, resolved at line capture ContractPrice → assigned PriceList → SalePrice and snapshotted IMMUTABLE at capture. ≠ step-2 discounts (promos/coupons/loyalty/employee compute OFF the captured base); ≠ markdowns (which WRITE SalePrice records — a list is READ-THROUGH at capture: nothing moves on a date, ZERO SCHEDULED_DUE growth; the resolve-time window IS the gating). THE CONTRACT SCOPE: orgCustomerId? — the lock's ContractPrice IS a PriceList scoped to ONE OrgCustomer, NOT a third construct: set at create, IMMUTABLE thereafter (the Edit shape excludes it — author a new list); a SCOPED list REQUIRES both window bounds (the contract TERM — STRICT). The effective window [startAt, endAt) is half-open and optional-per-side on an UNSCOPED list (absent = boundless); non-ACTIVE / out-of-window / org-unselected ⇒ the whole plane FALLS THROUGH silently at capture (the / degrade class — the LAPSE law STANDS: the effective SalePrice window remains REQUIRED, a plane hit overrides the captured VALUE only). Entries are child PriceListEntry dated windows (≤ 500 live per list); carrier law: a scoped list may be carried ONLY by its scoped OrgCustomer's priceListId, a CustomerPriceGroup carries UNSCOPED lists only. Org participation is the canned-pool selection (≤ 32; ABSENT = every org); at most 32 ACTIVE per org group (the create/reactivate gate). SEARCHABLE (the book law — the Promotion/LP/CPG/Affiliate operational-master class). Doom ← non-doomed OrgCustomer/CustomerPriceGroup carriers (the THIRD carrier-gated doom family); its OWN entries never block (they die with the plane at purge). NO UNIQ marker (captions are non-unique; nothing bearer-resolvable)." type PriceList { id: ID! "The group-scoped human-facing system id (PB-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a PriceList parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned-pool org selection — ABSENT = every org in the group; an org outside the pool makes the plane fall through at capture." organizationIds: [ID!] "The effective-window start (INCLUSIVE; UTC ISO-8601) — ABSENT = boundless below. Editable (a term renegotiation is an ordinary revision — the ENTRIES are the immutable price facts); REQUIRED on a scoped (contract) list." startAt: String "The effective-window end (EXCLUSIVE; UTC ISO-8601) — ABSENT = boundless above. Editable; REQUIRED on a scoped list (the contract term)." endAt: String "THE CONTRACT SCOPE: the ONE OrgCustomer this list is negotiated for. Set at create, IMMUTABLE; ABSENT = a general (assignable) list." orgCustomerId: ID } "One page of the priceLists listing — the records + the opaque resume cursor." type PriceListPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PriceList!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a PriceList. The tenant (org group) is derived SERVER-SIDE from the principal; ⚠ the caption IS the book name and is REQUIRED at the boundary (the CustomerPriceGroup divergence — an unnamed price book is meaningless; omission refuses VALIDATION/INVALID); the ACTIVE cap (≤ 32 per group) gates the create; orgCustomerId (the contract scope) resolves in-tenant + ACTIVE and REQUIRES both window bounds (the contract term — STRICT); when both bounds are supplied the half-open [startAt, endAt) window must be non-empty." input NewPriceListInput { "Optional: when omitted the per-type default applies — NONE — the CustomerPriceGroup divergence: the caption IS the book name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The canned-pool selection — ABSENT = every org in the group." organizationIds: [ID!] "The effective-window start (INCLUSIVE) — REQUIRED with endAt on a scoped list (the contract term)." startAt: String "The effective-window end (EXCLUSIVE)." endAt: String "THE CONTRACT SCOPE — the ONE OrgCustomer this list is negotiated for (in-tenant + ACTIVE; IMMUTABLE after birth). ABSENT = a general list." orgCustomerId: ID } "Edit-input for a PriceList. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). orgCustomerId is NOT editable (the contract scope is IMMUTABLE at birth, a contract is a contract: author a new list); window edits re-run the pairwise law at the boundary and the merged-doc cross-check kit-side (either half alone re-validates against the stored other — a scoped list can never shed its term)." input EditPriceListInput { "The book name." caption: String "Wholesale replace of the canned pool." organizationIds: [ID!] "The effective-window start — the window/scope law re-runs on the MERGED doc." startAt: String "The effective-window end — same law." endAt: String } "The single-axis target kinds." enum PriceListEntryTargetKind { variant category brand division } "The entry-value kinds." enum PriceListEntryValueKind { fixed percent_off_rrp cost_plus } "The single-axis merch target: kind selects the arm; exactly that arm's ref is present. category matches the SUBTREE rooted at the target." type PriceListEntryTarget { kind: PriceListEntryTargetKind! "variant: the exact sellable item." variantId: ID "category: the subtree root (deepest matching node wins within a list)." categoryId: ID "brand: the style's brand." brandId: ID "division: the merchandise division (derived from the category roots)." divisionId: ID } "The entry VALUE: fixed (a house MoneyEntry) · percent_off_rrp (percentPpm, EXCLUSIVE (0,1000000) — 100% off is not a price; off the Product rrp entry in the ORDER currency) · cost_plus (marginPpm, EXCLUSIVE (0,10000000) — over the II wmaCost). Rounding half-away-from-zero; non-applicability falls through at capture." type PriceListEntryValue { kind: PriceListEntryValueKind! "fixed: the window price (the strict decimal-string money grammar)." price: MoneyEntry "percent_off_rrp: the ppm off RRP ((0, 1000000))." percentPpm: Int "cost_plus: the ppm margin over wmaCost ((0, 10000000))." marginPpm: Int } "A PriceListEntry — ONE effective-dated price window per (list × single-axis merch target): the FOURTH DATED_SCHEDULE family (SalePrice → TaxRate → FxRate → this). List-parented (parentId = the PriceList ≠ rootId — the schedule dies with its list at purge). Windows are half-open [startAt, endAt) with endAt ALWAYS present (far-future = the standing price); no past starts; absent startAt = effective NOW (server-stamped). Inserts are splice-normalized per (list × targetKind × targetId) — classifySplice VERBATIM: a start falling STRICTLY inside the immediately-preceding window auto-TRIMS it (the ONE sanctioned in-place mutation — revisioned + evented); overlap with ANY OTHER record refuses CONFLICT/LIST_PRICE_WINDOW_OVERLAP naming the blockers (the family's OWN error row — the errors registry's ratified minting law). ≤1 EFFECTIVE entry per key at any instant BY the splice invariant — no uniqueness marker. Doom cancels a not-yet-effective FUTURE record only (an effective/lapsed record is IMMUTABLE price history — CONFLICT/IMMUTABLE; supersede it). The TARGET is a flag-discriminated SINGLE-axis ref (the commission-tuple class): variant | category | brand | division — category matches the SUBTREE rooted at the target (deepest node wins); IMMUTABLE with the window. The VALUE: fixed (house MoneyEntry) · percent_off_rrp (ppm off the Product's rrp entry in the ORDER currency) · cost_plus (ppm over the II's system-maintained wmaCost) — rounding half-away-from-zero; at capture a currency mismatch / absent basis / result ≤ 0 / unconvertible value FALLS THROUGH to the next plane; IMMUTABLE with the window (a renegotiated price is a NEW window — price history is fact). The edit surface is caption ONLY. ≤ 500 live entries per list (the create gate). NOT searchable (the SalePrice schedule-row class — reached via its list)." type PriceListEntry { id: ID! "The group-scoped human-facing system id (PE-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent PriceList; for a PriceListEntry parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The window start (INCLUSIVE; UTC ISO-8601) — set at birth (absent in the create input = effective NOW, server-stamped), IMMUTABLE thereafter." startAt: String! "The window end (EXCLUSIVE; UTC ISO-8601; ALWAYS present — far-future = the standing price). Moves ONLY via the system splice trim when a successor starts inside this window." endAt: String! "The single-axis merch target — IMMUTABLE with the window (re-target = a new entry)." target: PriceListEntryTarget! "The value — IMMUTABLE with the window (a renegotiated price is a NEW window; price history is fact)." value: PriceListEntryValue! } "One page of the priceListEntries listing — the records + the opaque resume cursor." type PriceListEntryPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PriceListEntry!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The single-axis target input: kind + EXACTLY that arm's ref." input PriceListEntryTargetInput { kind: PriceListEntryTargetKind! variantId: ID categoryId: ID brandId: ID divisionId: ID } "The entry-value input: kind + EXACTLY that arm's payload." input PriceListEntryValueInput { kind: PriceListEntryValueKind! price: MoneyEntryInput percentPpm: Int marginPpm: Int } "Create-input for a PriceListEntry. The tenant (org group) is derived SERVER-SIDE from the principal; priceListId (rides the header) is tenant-scoped server-side and must be NON-doomed (an inactive list legitimately STAGES prices — the SalePrice class); the target resolves in-tenant + live; the live-entry cap (≤ 500 per list) gates; startAt is optional (absent = effective NOW, server-stamped; explicit values must be >= the server now — no past starts) and must precede endAt." input NewPriceListEntryInput { "Optional: when omitted the per-type default applies — the window coordinate `# from `; when supplied it must be non-blank." caption: String "The PriceList id." priceListId: ID! "The single-axis target — resolved in-tenant + live server-side." target: PriceListEntryTargetInput! "The value." value: PriceListEntryValueInput! "The window start (INCLUSIVE). Optional — absent = effective NOW (server-stamped); explicit values must be >= the server now (no past starts)." startAt: String "The window end (EXCLUSIVE). ALWAYS required (far-future = the standing price); must be strictly after startAt." endAt: String! } "Edit-input for a PriceListEntry. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). startAt, endAt, target and value are NOT editable (wire-IMMUTABLE window facts, the SalePrice class — supersede with a new window or doom a FUTURE record and re-create; the system splice trim is the ONE sanctioned endAt move)." input EditPriceListEntryInput { caption: String } "One inline address-book entry." type ConsumerAddress { line1: String! line2: String city: String! "State / province / prefecture — optional (not universal across countries)." region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! "The book role: usable for shipping, billing, or both." addressType: String! "This entry is the book's default ship-to (at most ONE per book; requires a shipping-capable addressType)." isDefaultShipping: Boolean "This entry is the book's default bill-to (at most ONE per book; requires a billing-capable addressType)." isDefaultBilling: Boolean } "A Consumer — the B2C SHOPPER identity: WHO shops, as a per-merchant-group person (parentId === rootId — NOT a global identity; federated cross-merchant identity is the lock's flagged-not-now). B2C-SIMPLE INLINE: the NORMALIZED login email + displayName + bounded phones + the inline address book (≤16; shipping/billing roles + at most ONE default per side). the identity-marker rule: the (group × normalized email) UNIQ marker AMONG LIVE HOLDERS IS the login index — a live/suspended holder refuses CONFLICT/IDENTITY_TAKEN; ⚠ on erase (doom) the identifiers BURN within the group. FSM = the identity-family roster: active ⇄ suspended (the merchant abuse/fraud hold: punitive, ≠ the operational admin-pause; sessions go INERT via the live-status gate, reactivation restores) → doomed via erase (the DE-IDENTIFICATION terminal — PII scrub machinery lands; v1 the marker burns). Credentials NEVER ride this record; self-service rides the CONSUMER SESSION channel (consumerRegister/consumerLogin + the CONSUMER_SESSION_OPERATIONS roster); staff manage via THIS face. SEARCHABLE (the customer-book law). priceGroupId = the binding — the SUPERSEDE carrier: a consumer-named order resolves eligibility HERE, present-or-absent, NO member fall-through." type Consumer { id: ID! "The group-scoped human-facing system id (CN-…)." sysId: String! type: String! caption: String! "The FSM state: active | suspended | doomed." status: String! "The parent org group; for a Consumer parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The login identity — stored NORMALIZED (trim + lowercase, the class); the (group × email) UNIQ marker rides it." email: String! "The shopper display name; absent ⇒ the caption carries the identity line (the normalized email)." displayName: String "Contact phones — bounded (≤4); may be empty. A supplied list REPLACES WHOLESALE on edit." phones: [String!]! "The inline B2C address book — bounded (≤16); at most ONE default per side across the book; a supplied book REPLACES WHOLESALE on edit." addresses: [ConsumerAddress!]! "The CustomerPriceGroup binding. Gated in-tenant + ACTIVE at set; a group dying AFTER assignment DEGRADES at evaluation (never a cart-killing throw). Optional + editable." priceGroupId: ID "The Tag attachment set — wholesale-replace list, empty releases; absent = untagged. STAFF custody (the priceGroupId law): each ref gated in-tenant + ACTIVE; a tag with live wearers cannot be doomed. The segment tag axis reads it." tagIds: [ID!] "Preferred locale — canonical BCP-47 core (the ONE / locale shape, case-canonical STRICT: ll / ll-CC / ll-Ssss[-CC]); the i18n resolution consumes it." locale: String "DISPLAY-ONLY currency preference (ISO-4217 alpha-3, SHAPE + SET membership since): render prices in this currency where a conversion exists. ⚠ NEVER an evaluation input — carts/orders/documents stay org-currency." displayCurrency: String "Date-only YYYY-MM-DD, calendar-real, ≥ 1900-01-01; the not-in-the-future half rides the KIT write gate. Drives the age-restricted-sale gate WHEN that builds (data-only now — the named deferral) + the birthday registries." dateOfBirth: String "Contact-cadence preference AMONG CONSENTED channels — immediate | daily | weekly | monthly (canned v1 registry; enforcement = the comms build's named deferral)." commsFrequency: String "Message-format preference — plain | rich (canned v1 registry)." commsFormat: String "Comms topic interests ('about what') — ≤ 16, each trimmed 1..64; a supplied list REPLACES WHOLESALE on edit (the book law)." commsTopics: [String!] "General interest tags (the segment raw material) — ≤ 16, each trimmed 1..64; a supplied list REPLACES WHOLESALE on edit." interests: [String!] "The preferred store/LF: gated in-tenant + ACTIVE LF at write (the priceGroupId gate class); an LF dying LATER degrades at read — never a profile-killing throw." preferredLogicalFacilityId: ID } "One page of the consumers listing — the records + the opaque resume cursor." type ConsumerPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Consumer!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Address-book entry input for a Consumer — a supplied book REPLACES the stored one WHOLESALE (the Role-descriptors list-is-the-payload semantic)." input ConsumerAddressInput { line1: String! line2: String city: String! region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! "shipping | billing | both." addressType: String! isDefaultShipping: Boolean isDefaultBilling: Boolean } "Create-input for a Consumer. The tenant (org group) is derived SERVER-SIDE from the principal. ⚠ NO password field — credentials NEVER ride a construct shape: a staff-created Consumer is born WITHOUT self-service; resetConsumerPassword arms it. Self-registration (consumerRegister) shares this shape + a password argument." input NewConsumerInput { "Optional: when omitted the per-type default applies — the display name when given, else the NORMALIZED email (the identity line); when supplied it must be non-blank." caption: String "The login identity — normalized server-side; the (group × email) UNIQ marker reserves in the create transaction." email: String! displayName: String phones: [String!] addresses: [ConsumerAddressInput!] "Gated in-tenant + ACTIVE at set (the carrier law). ⚠ STAFF-only: the self-register lane (consumerRegister) refuses it." priceGroupId: ID "The Tag attachment set (at most 64, unique) — each ref gated in-tenant + ACTIVE. ⚠ STAFF-only: consumerRegister refuses it (the priceGroupId law)." tagIds: [ID!] "Preferred locale — canonical BCP-47 core (the ONE / locale shape, case-canonical STRICT: ll / ll-CC / ll-Ssss[-CC]); the i18n resolution consumes it." locale: String "DISPLAY-ONLY currency preference (ISO-4217 alpha-3, SHAPE + SET membership since): render prices in this currency where a conversion exists. ⚠ NEVER an evaluation input — carts/orders/documents stay org-currency." displayCurrency: String "Date-only YYYY-MM-DD, calendar-real, ≥ 1900-01-01; the not-in-the-future half rides the KIT write gate. Drives the age-restricted-sale gate WHEN that builds (data-only now — the named deferral) + the birthday registries." dateOfBirth: String "Contact-cadence preference AMONG CONSENTED channels — immediate | daily | weekly | monthly (canned v1 registry; enforcement = the comms build's named deferral)." commsFrequency: String "Message-format preference — plain | rich (canned v1 registry)." commsFormat: String "Comms topic interests ('about what') — ≤ 16, each trimmed 1..64; a supplied list REPLACES WHOLESALE on edit (the book law)." commsTopics: [String!] "General interest tags (the segment raw material) — ≤ 16, each trimmed 1..64; a supplied list REPLACES WHOLESALE on edit." interests: [String!] "The preferred store/LF: gated in-tenant + ACTIVE LF at write (the priceGroupId gate class); an LF dying LATER degrades at read — never a profile-killing throw." preferredLogicalFacilityId: ID } "Edit-input for a Consumer. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic); phones/addresses REPLACE WHOLESALE when supplied; an email edit is the identity-marker release/reserve swap (a live/suspended/doomed holder of the NEW value refuses CONFLICT/IDENTITY_TAKEN — the burn law; the OLD value releases). Serves BOTH the staff updateConsumer and the self-service updateMyConsumer (the same EditConsumer shape)." input EditConsumerInput { caption: String email: String displayName: String phones: [String!] addresses: [ConsumerAddressInput!] priceGroupId: ID "The replacement tag set (wholesale; empty releases; at most 64, unique; each ref in-tenant + ACTIVE). ⚠ STAFF-only: updateMyConsumer refuses it (the priceGroupId law)." tagIds: [ID!] "Preferred locale — canonical BCP-47 core (the ONE / locale shape, case-canonical STRICT: ll / ll-CC / ll-Ssss[-CC]); the i18n resolution consumes it." locale: String "DISPLAY-ONLY currency preference (ISO-4217 alpha-3, SHAPE + SET membership since): render prices in this currency where a conversion exists. ⚠ NEVER an evaluation input — carts/orders/documents stay org-currency." displayCurrency: String "Date-only YYYY-MM-DD, calendar-real, ≥ 1900-01-01; the not-in-the-future half rides the KIT write gate. Drives the age-restricted-sale gate WHEN that builds (data-only now — the named deferral) + the birthday registries." dateOfBirth: String "Contact-cadence preference AMONG CONSENTED channels — immediate | daily | weekly | monthly (canned v1 registry; enforcement = the comms build's named deferral)." commsFrequency: String "Message-format preference — plain | rich (canned v1 registry)." commsFormat: String "Comms topic interests ('about what') — ≤ 16, each trimmed 1..64; a supplied list REPLACES WHOLESALE on edit (the book law)." commsTopics: [String!] "General interest tags (the segment raw material) — ≤ 16, each trimmed 1..64; a supplied list REPLACES WHOLESALE on edit." interests: [String!] "The preferred store/LF: gated in-tenant + ACTIVE LF at write (the priceGroupId gate class); an LF dying LATER degrades at read — never a profile-killing throw." preferredLogicalFacilityId: ID } "The canned consent-purpose template keys." enum ConsentPurposeTemplateKey { marketing_email marketing_sms marketing_push analytics personalization data_sharing } "One canned consent-purpose template: usable via copyCannedConsentPurpose → an ordinary EDITABLE group ConsentPurpose (fork semantics — a copy never auto-revs)." type CannedConsentPurpose { key: ConsentPurposeTemplateKey! "The code the copy is born with (== the key; the merchant may re-code the copy — it is an ordinary row)." code: String! caption: String! "What the processing activity IS — the registry's human line (rows carry no description; captions + decorations do display duty)." description: String! "opt_in | opt_out — ALL six ship opt_in." consentModel: String! "The registry data version (port-stamped onto copies as templateVersion)." version: Int! } "A ConsentPurpose — the merchant-definable registry of WHAT consent can be requested for (group-parented master; GROUP-WIDE scope — per-org consent is the lock's flagged-not-now). Canned + custom AS THE ROLE MODEL WORKS: the 6 canned baselines are CODE-VIRTUAL versioned templates (cannedConsentPurposes lists them; copyCannedConsentPurpose materializes an ORDINARY EDITABLE group row — bootstrap materializes ZERO). Per-channel marketing granularity = DISTINCT purposes (GDPR consent is specific, never bundled). consentModel ∈ {opt_in, opt_out} — opt_in: an ABSENT record ⇒ DENIED (GDPR) · opt_out: an ABSENT record ⇒ ALLOWED until withdrawn (CCPA Do-Not-Sell) — ⚠ IMMUTABLE AFTER BIRTH. The code is the mutable machine handle — UNIQUE among NON-DOOMED per group via the consentPurposeCode UNIQ marker (the organizationCode class: edit = release/reserve swap; doom RELEASES [reissuable]; inactive HOLDS; a collision refuses CONFLICT/IDENTITY_TAKEN). DOOM is -gated by the everReferenced write-once stamp; DEACTIVATE is UNGATED. NOT searchable (config, not a book); NO description field (captions + decorations do display duty)." type ConsentPurpose { id: ID! "The group-scoped human-facing system id (PP-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a ConsentPurpose parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The machine-portable handle (^[a-z][a-z0-9_]{1,63}$; stored NORMALIZED trim+lowercase) — future comms/segments address purposes BY CODE. UNIQ among NON-DOOMED per group (the consentPurposeCode marker: edit swaps, doom releases, inactive holds; CONFLICT/IDENTITY_TAKEN on collision)." code: String! "opt_in | opt_out — the two consent regimes on ONE mechanism. ⚠ IMMUTABLE AFTER BIRTH — EditConsentPurposeInput deliberately omits it." consentModel: String! "PROVENANCE: the canned template this purpose was copied from (copyCannedConsentPurpose); PORT-stamped, never caller-suppliable; absent on from-scratch purposes. A copy NEVER auto-revs when the registry does (fork semantics)." templateKey: String "The canned-registry version the copy was compiled from (the templateKey twin; fork semantics)." templateVersion: Int "The WRITE-ONCE first-decision stamp: set TRUE inside the FIRST decide transaction against this purpose, never touched again. Present ⇒ doom refuses CONFLICT/REFERENCED; absent ⇒ virgin, dooms freely. Never caller-suppliable." everReferenced: Boolean } "One page of the consentPurposes listing — the records + the opaque resume cursor." type ConsentPurposePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ConsentPurpose!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for a FROM-SCRATCH ConsentPurpose. The tenant is derived SERVER-SIDE; ⚠ the caption IS the purpose's display name and is REQUIRED at the boundary (the CPG divergence — an unnamed processing activity is meaningless; omission refuses VALIDATION/INVALID); the code normalizes + its (group × code) UNIQ marker reserves in the create transaction. The canned lane is copyCannedConsentPurpose — NOT this shape." input NewConsentPurposeInput { "Optional: when omitted the per-type default applies — NONE — the CPG divergence: the caption IS the processing activity's display name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The machine handle — normalized server-side (trim+lowercase); the (group × code) UNIQ marker reserves in the create transaction (a NON-DOOMED holder refuses CONFLICT/IDENTITY_TAKEN; a doomed holder's code was RELEASED — reissuable)." code: String! "opt_in | opt_out — ⚠ IMMUTABLE after birth. guidance: opt_in IS the strict deny-by-default regime (all 6 canned baselines ship it)." consentModel: String! } "Edit-input for a ConsentPurpose. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic); a code edit is the consentPurposeCode marker release/reserve swap (a NON-DOOMED holder of the NEW code refuses CONFLICT/IDENTITY_TAKEN; the OLD code releases). ⚠ consentModel is NOT here — IMMUTABLE after birth; templateKey/templateVersion are port-stamped provenance, never editable (the Role law)." input EditConsentPurposeInput { "The processing activity's display name." caption: String "The machine handle — the marker swap rides the update transaction." code: String } "One myConsents row: the ACTIVE purpose's identity + regime, the caller's OWN decision state (absent = undecided — the purpose appears with the model default), and the RESOLVED effective verdict." type MyConsentRow { purposeId: ID! "The purpose's machine handle." code: String! caption: String! "opt_in | opt_out — decides the undecided default (opt_in ⇒ denied · opt_out ⇒ allowed; the GDPR+CCPA mechanism)." consentModel: String! "The caller's OWN record state (granted | withdrawn) — absent ⇒ no decision ever captured (the sparse law)." myStatus: String "The RESOLVED verdict — allowed | denied (the pure resolveEffectiveConsent truth table over live reads: consumer doomed ⇒ denied · purpose retired ⇒ denied · granted ⇒ allowed · withdrawn ⇒ denied · absent ⇒ the model default)." effective: String! "The policy version of the LATEST decision; absent ⟺ undecided." policyVersion: String "When the latest decision (or re-consent revision) was captured; absent ⟺ undecided." decidedAt: String } "One page of the myConsents view." type MyConsentRowPage { items: [MyConsentRow!]! "Present ⇒ more may remain (pass back verbatim as nextToken); null ⇒ the view is complete. Opaque + tenant-bound." nextToken: String } "A ConsentRecord — the PROOF-OF-DECISION per (Consumer × Purpose): CONSUMER-parented (parentId = the Consumer id — the LoyaltyMember construct-parented class), family document, SPARSE (a record materializes ONLY on an explicit decision — the ratified DUAL BIRTH: born directly granted on a grant, withdrawn on a withdraw [ruling 4 — an explicit 'no' is proof-of-refusal on EITHER model]). The PERMANENT (consumer × purpose) UNIQ pair marker is BOTH the singleton guarantee AND the O(1) lookup (never released, never taken over; purge reaps). FSM: granted ⇄ withdrawn (bidirectional forever — GDPR Art. 7(3), withdrawal as easy as granting) → doomed ONLY via system:consumer_erased. NO update op — the ONLY writes are the 4 decide ops (grantConsent/withdrawConsent staff · grantMyConsent/withdrawMyConsent consumer) + the system doom; a SAME-decision re-capture is a capture-context REVISION under a new policyVersion (re-consent — route 3; revisions keep every prior capture, the Art. 7(1) proof). Capture context ∈ {policyVersion, captureSurface ∈ [storefront, pos, back_office, cli, import], captureLocale?} reflects the LATEST decision. Effective consent = resolveEffectiveConsent (the myConsents view): consumer doomed ⇒ DENIED · purpose inactive/doomed ⇒ DENIED · granted ⇒ ALLOWED · withdrawn/doomed ⇒ DENIED · ABSENT ⇒ opt_in? DENIED: ALLOWED. AUDIT RIDES EXISTING MACHINERY — NO bespoke ledger. NOT searchable (PII-bearing proof — the stance)." type ConsentRecord { id: ID! "The group-scoped human-facing system id (CD-…)." sysId: String! type: String! caption: String! "The FSM state: granted | withdrawn | doomed." status: String! "The parent CONSUMER; rootId = the org group. NOT the family root." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The ConsentPurpose this decision is FOR (RI ✓ — in-tenant + ACTIVE at decide; a retired purpose refuses CONFLICT/REF_STATE naming it). Immutable at birth; the (parentId × purposeId) pair is singleton via the consentPair UNIQ marker." purposeId: ID! "The consent-notice/policy version PRESENTED at the LATEST decision. Re-consent under a NEW version with the SAME decision = the route-3 capture-context revision." policyVersion: String! "WHERE the latest decision was captured — storefront | pos | back_office | cli | import (canned v1 registry; 's banner vocabulary). The consumer channel is SERVER-FIXED storefront (a consumer session cannot claim an in-store capture); the staff lane REQUIRES one explicitly." captureSurface: String! "The locale PRESENTED at the latest decision (canonical BCP-47 core — the ONE / locale shape); absent ⇒ not recorded." captureLocale: String } "One page of the consentRecords listing — the records + the opaque resume cursor." type ConsentRecordPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ConsentRecord!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The typed CS-case resolution: return → an Return · goodwill_credit → an StoredValueInstrument (the store_credit direct lane) · replacement_order → an Order · info_only → ref-less." type CaseResolution { "return | goodwill_credit | replacement_order | info_only" kind: String! "The resolving construct (kind-typed; ABSENT on info_only — the per-kind ref law, validated in-tenant at set)." refId: ID } "The decision + attestedAt are write-once; billingChargeId follows the LIVE collection (a failed collection re-collects under the SAME case coordinate — the re-collection lane; the charge document's own status stays the money truth)." type CaseSupportBilling { "The root attestation instant (write-once)." attestedAt: String! "covered | charged — the coverage decision at attestation (write-once; a plan bought later never retro-covers)." decision: String! "The support_incident BillingCharge that stands (present iff charged; re-pointed by a re-collection — every attempt remains visible in billingCharges)." billingChargeId: ID "WHAT covered it — plan (a standing handholding plan) | onboarding (the wallet's complimentary first-90-days window). Present iff covered (write-once — the trail on the row)." coveredBy: String "THE WORDED STANDING: the merchant sentence for this fact, SERVER-composed at read (the Segment.refreshProblem worded-wire class): covered → the covered words · charged → the STANDING charge's live status worded (in flight / collected / FAILED — re-collection pending) · an unreadable/foreign charge degrades to the bare billed words (honest, never a leak). Reaches only the STAFF lanes by construction — the consumer lanes redact the whole block." standing: String! } "The transitionCsCase op vocabulary." enum CsCaseTransitionOp { "open → in_progress (authority:cs — begin working the case)." start "in_progress → pending_customer (waiting on the customer; a consumer reply AUTO-RESUMES — the addMyCaseMessage engine fires resume in the same commit)." await_customer "pending_customer → in_progress (the customer responded / staff resumes)." resume "in_progress → escalated (a higher support tier takes it)." escalate "escalated → in_progress (back to the working lane)." de_escalate "in_progress → resolved — ⚠ REQUIRES the resolution block PRESENT on the case." resolve "resolved → in_progress (the proposed resolution did not stick — BEFORE close; after close, reopen = a NEW linked case)." reopen_unresolved "resolved → closed (authority:cs; terminal ▣ immutable — legitimate history, stays listed; reopen = a NEW case via linkedFromCaseId). The resolved→closed row also carries the DORMANT system:auto_close twin." close "open|in_progress → cancelled (authority:cs; terminal ✦ doomed — spam/duplicate/withdrawn; drops from listings; NOT reopenable-by-link — ruling)." cancel } "A CsCase — ONE customer-support interaction (org-group-parented document; guest- OR Consumer-capable): the FSM head of a visibility-split CaseMessage thread. caseType ∈ {return_request, refund_inquiry, product_issue, complaint, general_inquiry, warranty_claim, shipping_issue, order_change, other} (canned + AT-extensible — the ContactRole registry class, never merchant free-form; MUTABLE via update, triage correction is routine CS — ruling). NO description field (ruling — the opening MESSAGE carries the narrative: one spine, zero duplicate state). origin is SERVER-STAMPED by lane (ruling — storefront = the consumer portal · staff = every staff create; IMMUTABLE, param-less). Refs are ref-ONLY (SPEC_CATALOG @375 — 'refs, not gate': validated in-tenant + non-doomed at write, but NO doom arms grow on the referenced constructs and consumer ERASE does NOT cascade here — cases are the MERCHANT's business records [ruling]; PII scrub =). consumerId/linkedFromCaseId/origin are IMMUTABLE at birth (rulings // — the edit face omits them; the CASEBOOK derived-index row a consumer-ref'd case mints in its create txn is thereby write-once). FSM: open(i) → in_progress ⇄ pending_customer (a consumer reply AUTO-RESUMES — the addMyCaseMessage engine fires caller_op:resume in the SAME commit) · in_progress ⇄ escalated · in_progress → resolved → closed (terminal ▣ immutable — REOPEN AFTER CLOSE = a NEW case linked via linkedFromCaseId, CLOSED-only [ruling]) · open|in_progress → cancelled (terminal ✦ doomed — spam/duplicate/withdrawn; drops from listings). resolved→closed also carries the DORMANT system:auto_close twin (its producer = the SLA machinery / policy build — parity-with-spec over trigger-pruning, ruling). resolve REQUIRES the typed resolution block PRESENT (the KIT gate — ruling, STRICT; deliberately NOT FSM data). priority/assignedTo/slaDueAt are MANUAL (the routing/SLA build populates them). The cs event domain's FIRST live producer (at.cs.case.* — ruling). NOT searchable (the book law covers WHO, not interactions)." type CsCase { id: ID! "The group-scoped human-facing system id (CS-…)." sysId: String! type: String! caption: String! "The FSM state: open | in_progress | pending_customer | escalated | resolved | closed | cancelled." status: String! "The parent org group; for a CsCase parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "return_request | refund_inquiry | product_issue | complaint | general_inquiry | warranty_claim | shipping_issue | order_change | other — the canned registry (AT-extensible, never merchant free-form). MUTABLE via update (ruling — triage correction)." caseType: String! "low | normal | high | urgent — kit-stamped 'normal' when the caller names none; manual." priority: String! "storefront | staff — WHERE the case originated, SERVER-STAMPED by lane (ruling; param-less). IMMUTABLE." origin: String! "The registered Consumer this case is FOR (absent = a guest case). ⚠ IMMUTABLE at birth (ruling — the CASEBOOK index row is write-once; guest→consumer linking = deferral 9). Ref-only: consumer erase does NOT cascade here (ruling)." consumerId: ID "The acted-upon Organization — ref-only, in-tenant + non-doomed at set." organizationId: ID "The disputed/acted-upon Order — ref-only (@375: no doom arm grows on it)." orderId: ID "The related Appointment — ref-only (the deferral 11, RESOLVED at the landing)." appointmentId: ID "The related Return — ref-only." returnId: ID "The related Fulfillment — ref-only." fulfillmentId: ID "The related Payment — ref-only." paymentId: ID "The Warranty a claim was filed against — stamped by fileClaimWarranty in the same transaction as the warranty’s claimed flip; never caller-typed. Ref-only." warrantyId: ID "The CLOSED case this one REOPENS (ruling — validated closed-EXACTLY at create; cancelled is NOT reopenable-by-link). IMMUTABLE at birth; the reopen provenance edge." linkedFromCaseId: ID "The assigned agent — an User (in-tenant + ACTIVE at set); teams/queues = (deferral 1)." assignedTo: ID "The SLA due instant (ISO-8601) — MANUAL; / populates by policy (deferral 1; the dormant system:auto_close consumes it then)." slaDueAt: String "The typed resolution block (ruling) — set via update BEFORE resolve fires. Per-kind ref law: info_only ref-LESS; every other kind names its resolving construct." resolution: CaseResolution "STAFF lanes only: the consumer lanes (myCase/myCases) REDACT it structurally (the ruling- visibility law at the field axis — platform billing is the MERCHANT’s business)." supportBilling: CaseSupportBilling } "One page of the csCases listing — the records + the opaque resume cursor." type CsCasePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CsCase!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Resolution input — staged via updateCsCase BEFORE the resolve transition; info_only carries NO refId, every other kind REQUIRES one (in-tenant + non-doomed, kind-typed)." input CaseResolutionInput { "return | goodwill_credit | replacement_order | info_only" kind: String! refId: ID } "The optional opening message on the STAFF create: appended in the SAME transaction as the case." input CsCaseInitialMessageInput { "The message body (1..4096)." body: String! "customer_visible | internal_note — the staff author's choice (internal_note NEVER crosses the consumer face — ruling)." visibility: String! } "Create-input for a CsCase. The tenant is derived SERVER-SIDE; ⚠ the caption IS the case's subject line and is REQUIRED at the boundary (the CPG divergence — an unnamed case is meaningless; omission refuses VALIDATION/INVALID). Refs validate in-tenant + non-doomed; linkedFromCaseId validates CLOSED-only (ruling); assignedTo validates in-tenant + ACTIVE. The optional initialMessage appends in the SAME transaction. The consumer lane is openMyCase — NOT this shape." input NewCsCaseInput { "Optional: when omitted the per-type default applies — NONE — the CPG divergence: the caption IS the subject line, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "return_request | refund_inquiry | product_issue | complaint | general_inquiry | warranty_claim | shipping_issue | order_change | other — the canned registry validates." caseType: String! "Defaults 'normal' when omitted." priority: String "The registered Consumer this case is FOR (omit = a guest case). ⚠ IMMUTABLE at birth (ruling) — a consumer-ref’d case mints its write-once CASEBOOK index row in the create transaction." consumerId: ID organizationId: ID orderId: ID appointmentId: ID returnId: ID fulfillmentId: ID paymentId: ID "The CLOSED case this one reopens (ruling — a non-closed target refuses CONFLICT/REF_STATE). IMMUTABLE." linkedFromCaseId: ID "In-tenant + ACTIVE User at set." assignedTo: ID "ISO-8601 instant — manual." slaDueAt: String "Optional opening message — appends in the SAME transaction (the consumer lane REQUIRES its body instead — ruling)." initialMessage: CsCaseInitialMessageInput } "Edit-input for a CsCase. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic; the updateConsumer law — the in-slice disclosure: a clearing lane arrives on demand). ⚠ consumerId/linkedFromCaseId/origin are NOT here — IMMUTABLE at birth (rulings //); status moves ONLY via transitionCsCase. Setting resolution here is the STAGED half of the resolve gate (ruling — stage the block, then fire resolve)." input EditCsCaseInput { "The subject line." caption: String "Registry-validated (ruling — triage correction)." caseType: String priority: String organizationId: ID orderId: ID appointmentId: ID returnId: ID fulfillmentId: ID paymentId: ID "In-tenant + ACTIVE User at set." assignedTo: ID slaDueAt: String "The typed resolution block (ruling) — per-kind ref law validated in-tenant at set." resolution: CaseResolutionInput } "The registry's inline ship-to override." type RegistryShipTo { line1: String! line2: String city: String! "State / province / prefecture — optional (not universal across countries)." region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! } "A GiftRegistry — ONE consumer-OWNED curated product list with purchase tracking (org-group-parented document): structurally a cousin of the Collection but consumer-owned + purchase-tracked. ownerConsumerId is a registered Consumer, IMMUTABLE at birth (ruling — the REGBOOK derived-index row minted in the create txn is thereby write-once; guests cannot own; transfer = deferral 14). registryType ∈ {wedding, baby, birthday, anniversary, holiday, wishlist, custom} (the seven VERBATIM — canned + AT-extensible, the caseType registry class; MUTABLE via update, a mislabel is routine correction). privacy ∈ {public | unlisted | private}, DEFAULT 'private' (strict — the owner opts INTO sharing); ⚠ the cross-consumer READ lanes that consume the gate are the storefront wave (ruling /deferrals 1–3) — until then privacy is enforced STRUCTURALLY (the consumer lane is owner-only). eventDate OPTIONAL — present ⇒ arms the scheduled active → expired (ruling — LIVE machinery, due == eventDate EXACTLY; the ExemptionCertificate optional-field class; grace/policy = deferral 7). FSM: active(i) → closed (caller_op:close · authority:own_registry) · active → expired (scheduled:scheduler — a LIVE non-terminal state: items stay readable, fulfillments still record [ruling], the owner can still doom) · closed|expired → doomed (caller_op:doom · authority:own_registry + referential_integrity — the inbound-ref set is EMPTY by design, subordinates are FAMILY [the CollectionMember vacuous-gate class]). Forbidden: active → doomed (close or let expire first). Ceilings: 16 ACTIVE registries/consumer · 200 ACTIVE items/registry. NOT searchable (consumer-owned, reached via its owner — the book law covers WHO, not their lists)." type GiftRegistry { id: ID! "The group-scoped human-facing system id (GR-…)." sysId: String! type: String! caption: String! "The FSM state: active | closed | expired | doomed." status: String! "The parent org group; for a GiftRegistry parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The OWNING registered Consumer. ⚠ IMMUTABLE at birth (ruling — the REGBOOK index row is write-once; ownership transfer = deferral 14)." ownerConsumerId: ID! "wedding | baby | birthday | anniversary | holiday | wishlist | custom — the canned registry (AT-extensible, never merchant free-form). MUTABLE via update." registryType: String! "public | unlisted | private — born 'private' when the caller names none (strict). ⚠ Structurally DORMANT until gives it a cross-consumer reader (ruling — the consumer lane is owner-only)." privacy: String! "The event instant (ISO-8601, a FULL instant — the slaDueAt convention). Present ⇒ arms the scheduled expiry (ruling — due == eventDate EXACTLY; edits re-arm/disarm on write)." eventDate: String "The registry-specific ship-to override." shipTo: RegistryShipTo } "One page of the giftRegistries listing — the records + the opaque resume cursor." type GiftRegistryPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [GiftRegistry!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Ship-to input for a GiftRegistry — a supplied block REPLACES the stored one WHOLESALE." input RegistryShipToInput { line1: String! line2: String city: String! region: String postalCode: String "ISO 3166-1 alpha-2 country code (uppercase)." countryCode: String! } "Create-input for a GiftRegistry. The tenant is derived SERVER-SIDE; ⚠ the caption IS the registry's name and is REQUIRED at the boundary (the CsCase divergence — an unnamed registry is meaningless). consumerId names the OWNER; the ACTIVE-registries ceiling gates kit-side. The consumer lane is createMyGiftRegistry — NOT this shape (the principal stamps as owner there)." input NewGiftRegistryInput { "Optional: when omitted the per-type default applies — NONE — the CsCase divergence: the caption IS the registry name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "wedding | baby | birthday | anniversary | holiday | wishlist | custom — the canned registry validates." registryType: String! "The OWNING registered Consumer (ruling — the staff lane names it; live-gated: registered + NOT-doomed). ⚠ IMMUTABLE at birth (ruling)." consumerId: ID! "Defaults 'private' when omitted (strict)." privacy: String "ISO-8601 instant — present ⇒ arms the scheduled expiry (ruling)." eventDate: String "The inline ship-to override." shipTo: RegistryShipToInput } "Edit-input for a GiftRegistry. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic; the updateCsCase law). ⚠ ownerConsumerId is NOT here — IMMUTABLE at birth (ruling; transfer = deferral 14); status moves ONLY via close/doom (+ the scheduled expiry). privacy and eventDate stay editable while the registry lives — an eventDate edit RE-ARMS/DISARMS the scheduled due on the SAME write (the heal-on-write law)." input EditGiftRegistryInput { "The registry name." caption: String "Registry-validated (a mislabel is routine correction)." registryType: String privacy: String "Re-arms/disarms the scheduled expiry on write (ruling)." eventDate: String "REPLACES wholesale." shipTo: RegistryShipToInput } "The transitionReview op vocabulary." enum ReviewTransitionOp { "pending → approved." approve "approved → published." publish "pending → rejected." reject "published → removed · approved → removed." remove } "A Review — ONE consumer product review (org-group-parented document): authorConsumerId (a registered Consumer) × targetProductId (a Product, the consumer-facing unit) BOTH IMMUTABLE at birth. rating 1–5 (integer). ⚠ verifiedPurchase is SERVER-STAMPED, NEVER client-asserted. FSM (moderation default-on, strict): pending(i) → approved (caller_op:approve / the DORMANT system:auto_publish_policy twin, deferral 6) · approved → published (caller_op:publish / the DORMANT system:auto twin) · pending → rejected · published|approved → removed — EVERY caller edge authority:moderate; pending → published FORBIDDEN (moderation is never skippable). rejected✦/removed✦ are BOTH doomed terminals (lists filter them; the marker frees by TAKEOVER). The STAFF face is moderation-ONLY (ruling — {create:false, update:false}: staff never author or edit authorial consumer content; the author writes via submitMyReview/updateMyReview [an ordinary revision — edits NEVER re-enter moderation; moderators hold remove]). Consumer erase does NOT cascade (ruling — scrubs). Display/rendering = (deferral 4); the aggregate rating read-model = (deferral 5); photos/Q&A/votes/replies = ratified-out. NOT searchable (reached via its target — authorial content, not a master book)." type Review { id: ID! "The group-scoped human-facing system id (RE-…)." sysId: String! type: String! caption: String! "The FSM state: pending | approved | published | rejected | removed." status: String! "The parent org group; for a Review parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The authoring registered Consumer. ⚠ IMMUTABLE at birth (the marker identity — ruling)." authorConsumerId: ID! "The reviewed Product. ⚠ IMMUTABLE at birth (the marker identity; re-target = a NEW review after removal)." targetProductId: ID! "1–5 (integer — no halves at v1)." rating: Int! "The review headline (1..200)." title: String! "The review narrative (1..8192)." body: String! "SERVER-STAMPED (ruling — pointed-proof; NEVER client-asserted). Author edits supplying orderId re-derive it." verifiedPurchase: Boolean! "The proving Order — present IFF verifiedPurchase (the stamp carries its provenance)." verifiedByOrderId: ID } "One page of the reviews listing — the records + the opaque resume cursor." type ReviewPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Review!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The / auto-top-off configuration: balance < thresholdTokens → auto-purchase amountUsdCents of tokens via the stored method, UNLESS the month's cumulative auto-spend would exceed budgetCapUsdCents — then STOP + WARN (never charges past the merchant's budget). The FIRING engine is the billing charger's top-off arm." type AutoTopOffConfig { enabled: Boolean! "Fire when the balance drops below this (tokens)." thresholdTokens: Int! "The fixed $$ amount each fire purchases (USD cents)." amountUsdCents: Int! "The month's auto-spend ceiling (USD cents) — reached ⇒ STOP + warn." budgetCapUsdCents: Int! "The DAY's auto-spend ceiling (USD cents; the operator's per-day budget). Null = the month cap alone governs." dailyCapUsdCents: Int } "The stored off-session method's wire-readable facts. The three fields live and die together (attach stamps, detach removes whole)." type BillingMethodFacts { "The card network (visa | mastercard | …) — the processor's word." brand: String! "The card's last four digits." last4: String! "When the method attached (UTC ISO)." attachedAt: String! } "A TokenAccount — **the ONE-per-GROUP token wallet / platform billing unit** (AT/stack billing of MERCHANTS; 1 org or 100 orgs share ONE pool — is the billing aggregation point; per-org figures are consumption ATTRIBUTION, reporting-only). The wallet is a GROUP-scoped SINGLETON enforced by the tokenAccountSingleton UNIQ marker minted IN the create txn. **Wallet existence IS the metering arm** (ruling): no wallet ⇒ the group is unbilled (the DVLP posture); opening one arms the rater (the slice-4 leg). balance = Σ TokenEntry amounts EXACTLY, cached in the SAME transaction as every ledger append — SIGNED (ruling: the ledger never lies; a transient sub-zero overshoot is honest state; exhaustion balance ≤ 0 fires the system:token_exhaustion CASCADE-suspend of member orgs, reload ≤0→>0 fires system:token_reload unsuspend-to-ACTIVE). The auto-top-off block is CONFIG this slice (the FIRING engine + stored-method custody = the rater leg, deferral 5); its budget cap is a LAZY month-keyed counter (ruling — rolls by key comparison, no scheduled reset). FSM: active(i) ⇄ inactive (paused — purchases/grants refuse REF_STATE; the rater still debits: usage happened) → doomed (gate-protected; the inbound-ref set is EMPTY by design — entries and purchases are FAMILY [the GiftRegistry vacuous-gate class]). Platform billing is USD-only. NOT searchable (platform-internal — never merchant search content). Template class A16_BILLING (platform billing ≠ floor work — owner/manager/assoc_mgr; hand-derived v23)." type TokenAccount { id: ID! "The group-scoped human-facing system id (TA-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a TokenAccount parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The cached token balance = Σ TokenEntry amounts EXACTLY — SIGNED. NEVER caller-writable — moves ONLY with ledger appends." balance: Int! "The low-balance warning threshold (tokens) — absent ⇒ the warning arm is unarmed (the eventDate optional-arm class). The warning ladder is EVENTS + readable state now." lowBalanceThreshold: Int "The daily-burn alert threshold in KERNELS/day. Absent ⇒ unarmed. Owner-set like lowBalanceThreshold; day rows over it read as breaches on the costs face (the engine-evented twin is a named wordable beside delivery)." dailyBurnThresholdKernels: Int "The auto-top-off block — absent ⇒ never fires. CONFIG this slice; the FIRING engine + stored-method custody ride the rater leg. Cap reached ⇒ STOP + WARN (never charges past the budget — the operator law)." autoTopOff: AutoTopOffConfig "The auto-top-off cap window's YYYY-MM month key — SERVER-stamped at fire time." autoTopOffMonth: String "The month's cumulative auto-top-off spend — SERVER-stamped at fire; compared against the cap BEFORE each fire." autoTopOffSpentUsdCents: Int "The auto-top-off DAY window's YYYY-MM-DD key." autoTopOffDay: String "The DAY's cumulative auto-top-off spend." autoTopOffSpentDayUsdCents: Int "WHICH stored card the in-flight top-off charged — primary | backup." autoTopOffPendingMethod: String "The UTC day the PRIMARY card last webhook-failed a top-off." autoTopOffPrimaryFailedDay: String "The backup twin — both stamps reading TODAY = the cards-failing emergency (nothing fires; the loud lane speaks each tick)." autoTopOffBackupFailedDay: String "The BACKUP method's readable facts. The charger's top-off falls back to it when the primary declines; stamped by attachTokenAccountBackupBillingMethod, removed whole by its detach." backupBillingMethod: BillingMethodFacts "COMPUTED at read: the group's total kernel consumption over the LAST 7 UTC days, summed off the rater's TOTAL day lanes (the usageReport engine — exact integers). 0 on a quiet week; null only on the filtered listing lane (vitals ride the plain reads)." burn7dKernels: Int "COMPUTED at read: the balance SCALED TO KERNELS (balance is whole internal tokens — ×1,000,000) ÷ the 7-day daily kernel burn — how many days the balance lasts at the current rate. Null when the burn is 0 (no rate exists to project) or on the filtered listing lane." runwayDays: Float "The sub-token usage accrual in µtokens, 0…999,999. SERVER-stamped — no face carries it; absent = 0. Read-exposed for transparency." microTokenCarry: Int "When the CURRENT low-balance episode began. The readable half of the warning ladder — the at.billing.token_account.low_balance.v1 event is its evented twin." lowBalanceSince: String "The stored off-session method's READABLE facts. Present ⟺ custody is armed (the charger's top-off + base-fee arms both require it); stamped by attachTokenAccountBillingMethod, removed whole by detach." billingMethod: BillingMethodFacts "The in-flight auto-top-off TokenPurchase. Absent = no fire in flight." autoTopOffPendingPurchaseId: ID "When the CURRENT capped episode began. Absent/null = not capped." topOffCappedSince: String "The latest UTC YYYY-MM period the base fee SETTLED for. Absent = never collected." baseFeePaidMonth: String "The live included-allowance month, UTC YYYY-MM. SERVER-stamped by the base-fee settle; absent/null = no allowance ever minted, or the plain-read vitals lane was skipped (the burn7dKernels listing-lane class)." includedMonth: String "What the live allowance month MINTED (tokens — monthlyIncludedTokensFor at the collected amount). Present ⟺ includedMonth is." includedGranted: Int "What the live allowance month has NOT yet drawn (tokens; drains floor-0 as the month meters; 0 after the month-roll expiry sweep). The banked balance = balance − this figure while the month lives. Present ⟺ includedMonth is." includedRemaining: Int "Your group’s SPENDABLE referral-earnings credit (USD cents ≥ 0): Σ your AffiliateAccrual entries exactly. When it covers your monthly base fee the cycle CREDIT-SETTLES automatically (no card charge — bill-netting first, the ruled settlement order). Absent/null = never earned a cent, or the filtered listing lane (the burn7dKernels class)." affiliateCreditCents: Int "Σ kernels in transfer-FROZEN blocks: your TRUE spendable room = balance − this figure (the exhaustion gate reads it; the transfer face’s pre-submit warning derives from it). Absent/null = nothing frozen, or the filtered listing lane." frozenKernels: Int "The latest UTC YYYY-MM-DD day a storage snapshot EMITTED for this wallet. Absent = never snapshotted." storageSnapshotDay: String "Platform billing currency — 'USD' by law." currency: String! } "One page of the tokenAccounts listing — the records + the opaque resume cursor." type TokenAccountPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TokenAccount!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Auto-top-off input for a TokenAccount." input AutoTopOffConfigInput { enabled: Boolean! thresholdTokens: Int! amountUsdCents: Int! budgetCapUsdCents: Int! "the optional per-day ceiling — must cover ≥ one amountUsdCents fire and ≤ the month cap (the coherence refines)." dailyCapUsdCents: Int } "Create-input for the group's TokenAccount." input NewTokenAccountInput { "Optional: when omitted the per-type default applies — 'group token wallet' (the wallet is functional infrastructure, not a named artifact); when supplied it must be non-blank." caption: String "≥ 0 — arms the low-balance warning." lowBalanceThreshold: Int "≥ 1 — arms the daily-burn alert (kernels/day)." dailyBurnThresholdKernels: Int "The auto-top-off CONFIG (the firing engine = the rater leg)." autoTopOff: AutoTopOffConfigInput } "Edit-input for a TokenAccount. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). ⚠ balance and the cap counters are NEVER caller-writable (balance moves only with ledger appends; the counters are server-stamped at auto-top-off fire); currency is fixed USD. A supplied autoTopOff block REPLACES the stored one wholesale." input EditTokenAccountInput { "The wallet's display caption." caption: String "≥ 0." lowBalanceThreshold: Int "≥ 1 (kernels/day)." dailyBurnThresholdKernels: Int "REPLACES wholesale." autoTopOff: AutoTopOffConfigInput } "A TokenPurchase — buying platform tokens with real money (**Stripe primary**; ACH/wire/invoiced = deferral 7): $ → tokens at the volume tier (tier_1 | tier_2 | tier_3 — SERVER-computed, never client-asserted), loaded into the GROUP's TokenAccount as a purchase TokenEntry when the webhook settles. **AT/stack charging the MERCHANT** — the platform account's OWN PaymentIntent (distinct from the merchant's customer Payments and the Connect plane). **NON-REFUNDABLE**. The FSM is the ratified 3-STATE table VERBATIM: created(i) → succeeded ▣ / failed ✦, BOTH edges system:stripe_webhook — NO caller transitions and NOTHING mutable between birth and settlement ⇒ the wire realizes {create:true, update:false, transitions:false} (a NEW suppression combination — the webhook-settled document). The birth op mints the TEST PaymentIntent api-side with the LOAD-BEARING metadata {at_kind, tokenPurchaseId, rootId} (ruling — the lesson: PI metadata IS the join key; the EXISTING platform 8-event endpoint roster covers the lane — payment_intent.succeeded/payment_failed/canceled; canceled settles failed). The real-money gate = classification × Stripe MODE (ruling: live-mode charges require a production-classified group; test-mode is legal for ANY classification — that is how the goldens run; the mode derives from the custodied key, never asserted). Purchase-abandon reconciliation beyond canceled = deferral 14a. NOT searchable. Template class A16_BILLING (hand-derived v23)." type TokenPurchase { id: ID! "The group-scoped human-facing system id (TP-…)." sysId: String! type: String! caption: String! "The FSM state: created | succeeded | failed." status: String! "The parent TokenAccount; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The charge magnitude, USD cents (platform billing is USD). 500..10000000." usdAmountCents: Int! "The SERVER-computed token load at the volume tier." tokensPurchased: Int! "tier_1 | tier_2 | tier_3 — the tier that priced it (replayability with rateCardVersion)." volumeTierCode: String! "The rate-card/tier config version in force at birth." rateCardVersion: Int! "The platform Stripe PaymentIntent (pi_… — SERVER-stamped at birth; the webhook join key, ruling)." stripePaymentIntentId: String! "When the webhook settled it (stamped at succeeded/failed; absent while created)." settledAt: String } "One page of the tokenPurchases listing — the records + the opaque resume cursor." type TokenPurchasePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TokenPurchase!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a TokenPurchase. Below the tier-1 floor there is no price → VALIDATION refuses." input NewTokenPurchaseInput { "Optional: when omitted the per-type default applies — 'token purchase $' (derived from the USD amount at birth); when supplied it must be non-blank." caption: String "500..10000000 (the tier-1 floor is the minimum purchase)." usdAmountCents: Int! } "A BillingCharge — the money rail's NON-TOKEN platform fee: AT/stack charging the MERCHANT the platform fee (chargeKind base_fee | support_plan | support_incident — extensible; the $15/mo fee is the first rail, its amount code-carried in BILLING_BASE_FEE_USD_CENTS — **: $5 overhead + $10 that converts to kernels at settle; those kernels are THAT MONTH's allowance — spend first, expire with the month; only purchased kernels bank**). **The API face is FULLY suppressed** — {create:false, update:false, transitions:false}, a NEW suppression combination (the lineage: the SAGA class suppresses because the SYSTEM writes, the Review class because the CONSUMER does, the TokenPurchase pair because the PROCESSOR settles — THIS one because the PLATFORM ITSELF both mints and settles): the wire surface is the 2 generated READS, the merchant's transparency lane. NOT searchable. Template class A16_BILLING (hand-derived v24)." type BillingCharge { id: ID! "The group-scoped human-facing system id (BC-…)." sysId: String! type: String! caption: String! "The FSM state: created | succeeded | failed." status: String! "The parent TokenAccount (the custody anchor — charges ride the wallet's stored method); rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "base_fee | support_plan | support_incident — what the fee is." chargeKind: String! "The fee magnitude, USD cents — resolved from config at mint (base_fee → BILLING_BASE_FEE_USD_CENTS; the settle converts the beyond-overhead share to kernels — monthlyIncludedTokensFor); the stamp IS the replay record (the amount in force when the cycle fired)." usdAmountCents: Int! "The billing period this charge covers (UTC YYYY-MM) — the charge-once coordinate (the UNIQ marker rides group × kind × month)." periodMonth: String! "The platform off-session Stripe PaymentIntent (pi_… — SERVER-stamped at birth; the webhook join key, ruling)." stripePaymentIntentId: String! "When the webhook settled it (stamped at succeeded/failed; absent while created)." settledAt: String } "One page of the billingCharges listing — the records + the opaque resume cursor." type BillingChargePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [BillingCharge!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One ref-ONLY bound to a live domain construct." type TaskConstructRef { "The referenced construct's declared type (verified against the live record at write)." type: String! "The referenced construct's id." id: ID! } "The transitionTask op vocabulary." enum TaskTransitionOp { "open → in_progress (authority:task — begin working)." start "in_progress → open (back to the inbox — the working-lane retreat; occ-only)." unstart "open|in_progress|postponed → completed (authority:task; terminal ▣ immutable, doomed:false — legitimate history; the USER/TEAM book rows REMOVE in the same txn; reopen = a NEW task via linkedFromTaskId, closing a parked ask never forces a detour through open)." complete "open|in_progress|postponed → cancelled (authority:task; terminal ✦ doomed — abandoned/duplicate/mistaken; drops from listings; NOT reopenable-by-link)." cancel "postponed → open (“Return now” — the caller pulls the parked ask back to the inbox before its returnAt; the USER/TEAM book rows RE-MINT in the same txn; the boomerang's scheduled twin fires the SAME flip at returnAt via the sweep; occ-only — the unstart retreat class)." unpostpone } "The CsCase chassis reused: caption REQUIRED (the subject line) + its OWN description field (≤8192 — the task's brief; the conversation is the generic Note thread at NOTE#, addNote/notes). priority ∈ {low, normal, high, urgent} (its OWN canned registry — kit-stamped 'normal' when unnamed). createdBy is SERVER-STAMPED (IMMUTABLE); reportTo names WHO the work reports to. Assignment is MULTI: assigneeUserIds ≤8 + teamIds ≤4 (in-tenant + ACTIVE at set) — each holds a write-once TASKBOOK inbox row while the task LIVES (terminal transitions remove USER/TEAM rows in the SAME txn: the inbox self-prunes, bounded by open work). labelIds ≤16 (TaskLabel — the work vocabulary). constructRefs ≤16 {type,id} bind LIVE domain constructs REF-ONLY (the CsCase @375 law: validated in-tenant + non-doomed at write, NO doom arms grow, a purged target renders as a tombstone; each holds a TASKBOOK#REF row while the task is non-doomed — the tasksByConstruct lane). dueAt: overdue = COMPUTED at read (dueAt < now ∧ live; + the dueBefore filter) — NO sweep lane in v1 (the overdue-vitals/notification lane = a NAMED deferral). FSM: open(i) ⇄ in_progress (start/unstart — the inbox retreat) · open|in_progress → postponed (postponeTask — the boomerang: returnAt future-only; the USER/TEAM inbox rows PRUNE [parking means quiet — the REF row stays]; the scheduled-due sweep fires postponed→open AT returnAt, or “Return now” [unpostpone] pulls it back early — either return RE-MINTS the inbox rows) · open|in_progress|postponed → completed (terminal ▣ immutable, doomed:false — legitimate history; REOPEN = a NEW task via linkedFromTaskId, COMPLETED-only) · open|in_progress|postponed → cancelled (terminal ✦ doomed — lists filter it; NOT reopenable-by-link). 'blocked' is deliberately NOT a state — it is a label (no machine consequence in v1). SEARCHABLE by caption (the law; ⚠ the WIRE enum joins at the deploy leg). The ops event domain (at.ops.task.* — the facility→ops neighborhood)." type Task { id: ID! "The group-scoped human-facing system id (TK-…)." sysId: String! type: String! caption: String! "The FSM state: open | in_progress | postponed | completed | cancelled." status: String! "The parent org group; for a Task parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The task's own brief (≤8192: ≠ the CsCase message-spine ruling; the Note thread is the conversation). Absent = caption-only." description: String "low | normal | high | urgent — kit-stamped 'normal' when the caller names none (its OWN registry — the CS shape, deliberately not shared)." priority: String! "WHO opened the task — SERVER-STAMPED from the acting principal; IMMUTABLE. NULL exactly when systemOrigin is set." createdBy: ID "WHICH platform lane minted the task when NO human did. NEVER caller-suppliable — absent from create/edit inputs by law; IMMUTABLE at birth; null on every human-created task." systemOrigin: String "WHO the work reports to — an User (in-tenant + ACTIVE at set); the notification lane = the deferral." reportTo: ID "The assigned workers." assigneeUserIds: [ID!]! "The assigned Teams (≤4, distinct; in-tenant + ACTIVE at set; each holds a TASKBOOK#TEAM inbox row while the task lives)." teamIds: [ID!]! "The work labels (≤16, distinct; in-tenant + ACTIVE TaskLabels at set)." labelIds: [ID!]! "The expected-completion instant (ISO-8601) — overdue is COMPUTED at read (dueAt < now ∧ live), never stored." dueAt: String "COMPUTED at read via the ONE isTaskOverdue home (dueAt < now ∧ live; never stored, so nothing exists to drift; completed the wire face the prose promised)." overdue: Boolean! "The bound domain constructs (≤16, distinct by (type,id) — REF-ONLY per the CsCase @375 law: no doom arms grow; a purged target renders as a tombstone)." constructRefs: [TaskConstructRef!]! "The COMPLETED task this one REOPENS. IMMUTABLE at birth; the reopen provenance edge." linkedFromTaskId: ID "The boomerang instant: while status=postponed the scheduled-due sweep fires postponed→open AT this instant (re-minting the USER/TEAM inbox rows); after the return it stays as honest history (the armed law reads STATUS). Never on the edit face; a re-park restamps it." returnAt: String "SERVER-stamped, IMMUTABLE, all-three-or-none with the anchor pair; null on hand-created tasks." originNoteId: ID "The origin note's annotated construct type (the /comments face's anchor — the come-back link is /comments//)." originAnchorType: String "The origin note's annotated construct id (the polymorphic arm — the sibling names the type; the ApprovalRequest targetType precedent)." originAnchorId: ID } "One page of the tasks listing — the records + the opaque resume cursor." type TaskPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Task!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Construct-ref input." input TaskConstructRefInput { type: String! id: ID! } "Create-input for a Task. The tenant is derived SERVER-SIDE; ⚠ the caption IS the task's title and is REQUIRED at the boundary (the CsCase stance — an unnamed task is meaningless). Assignees/teams/labels validate in-tenant + ACTIVE; refs validate in-tenant + non-doomed; linkedFromTaskId validates COMPLETED-only. The TASKBOOK inbox rows for the birth sets mint in the SAME transaction." input NewTaskInput { "Optional: when omitted the per-type default applies — NONE — the CsCase divergence class: the caption IS the task title, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The task's brief (≤8192)." description: String "Defaults 'normal' when omitted." priority: String "In-tenant + ACTIVE User at set." reportTo: ID "≤8 distinct in-tenant ACTIVE Users; omit = unassigned (the inbox open state)." assigneeUserIds: [ID!] "≤4 distinct in-tenant ACTIVE Teams." teamIds: [ID!] "≤16 distinct in-tenant ACTIVE TaskLabels." labelIds: [ID!] "ISO-8601 instant." dueAt: String "≤16 distinct (type,id) refs — in-tenant + non-doomed at write (ref-only)." constructRefs: [TaskConstructRefInput!] "The COMPLETED task this one reopens. IMMUTABLE." linkedFromTaskId: ID } "Edit-input for a Task. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic; the updateCsCase law). The id-set fields REPLACE their sets. ⚠ createdBy/linkedFromTaskId are NOT here — IMMUTABLE at birth; status moves ONLY via transitionTask; a terminal task refuses every edit (CONFLICT/IMMUTABLE)." input EditTaskInput { "The task title." caption: String "≤8192." description: String priority: String "In-tenant + ACTIVE User at set." reportTo: ID "REPLACES the assignee set (the book rows follow in the same txn)." assigneeUserIds: [ID!] "REPLACES the team set." teamIds: [ID!] "REPLACES the label set." labelIds: [ID!] dueAt: String "REPLACES the ref set (the REF book rows follow)." constructRefs: [TaskConstructRefInput!] } "A Team — a named group Users inside ONE org group (org-group-parented master — the Role/Brand class). Built DOMAIN-NEUTRAL by ruling: Tasks v1 is merely the FIRST consumer (task teamIds + the TASKBOOK#TEAM inbox lane, teamTasks); the CS routing/queues build consumes it later WITHOUT reshaping (the CsCase assignedTo doc's own deferral resolves construct-side HERE). memberUserIds is a BOUNDED distinct set (≤100; a larger org models sub-teams, not a mega-list; every member in-tenant + ACTIVE at set); leadUserId MUST be a member (strict). FSM: active(i) ⇄ inactive → doomed. SEARCHABLE by caption (the law — a team book is name-found; ⚠ the WIRE enum joins at the deploy leg). The identity event domain (at.identity.team.* — teams group identity-domain principals)." type Team { id: ID! "The group-scoped human-facing system id (TM-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Team parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The member Users (≤100, distinct; in-tenant + ACTIVE at set)." memberUserIds: [ID!]! "The team lead — MUST be a member (strict); absent = no designated lead." leadUserId: ID } "One page of the teams listing — the records + the opaque resume cursor." type TeamPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Team!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Team. The tenant is derived SERVER-SIDE; ⚠ the caption IS the team name and is REQUIRED at the boundary (an unnamed team is meaningless). Members validate in-tenant + ACTIVE; the lead must be among the supplied members." input NewTeamInput { "Optional: when omitted the per-type default applies — NONE — the CsCase divergence class: the caption IS the team name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "≤100 distinct in-tenant ACTIVE Users; omit = an empty team (named before staffed)." memberUserIds: [ID!] "Must be among the supplied members." leadUserId: ID } "Edit-input for a Team. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). memberUserIds REPLACES the set (revalidated whole); the lead-∈-members law re-checks against the POST-edit set (an edit that orphans the standing lead refuses — clear or move the lead in the same edit). status moves ONLY via the transition ops." input EditTeamInput { "The team name." caption: String "REPLACES the member set." memberUserIds: [ID!] "Must be a member of the post-edit set." leadUserId: ID } "A TaskLabel — the WORK vocabulary: a group-defined label attached to Tasks by reference (labelIds). DELIBERATELY its OWN master, NOT a reuse of the catalog Tag — catalog vocabulary (what we sell) and work vocabulary (how we operate) must not blend, and dooming a work label must never referential-gate against catalog nodes. The Tag SHAPE otherwise (caption + optional #rrggbb color; free-string labels stay unrepresentable — typo-proof, rename-safe via caption). FSM: active(i) ⇄ inactive → doomed (the template — ≠ the Tag's two-state: work vocabulary retires seasonally and comes back, so inactive earns its keep; 'blocked' lives HERE as a label because it has no machine consequence — the disclosed states-vs-labels lean). NOT searchable (supporting vocabulary — the Decoration SB-d class; reached via the tasks list filter, never name-found). The ops event domain (at.ops.task_label.*)." type TaskLabel { id: ID! "The group-scoped human-facing system id (LB-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a TaskLabel parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Optional display color (#rrggbb, lowercase-normalized); absent ⇒ the surface default chip." color: String } "One page of the taskLabels listing — the records + the opaque resume cursor." type TaskLabelPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TaskLabel!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a TaskLabel. The tenant is derived SERVER-SIDE; ⚠ the caption IS the label text and is REQUIRED at the boundary." input NewTaskLabelInput { "Optional: when omitted the per-type default applies — NONE — the CsCase divergence class: the caption IS the label text, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "#rrggbb hex (lowercase)." color: String } "Edit-input for a TaskLabel. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). status moves ONLY via the transition ops." input EditTaskLabelInput { "The label text." caption: String "#rrggbb hex (lowercase)." color: String } "A device hardware class: the 4 native POS surfaces + the in-Office browser POS + the Pi legacy-peripheral bridge. Canned + AT-extensible — added by the platform, never merchant-defined." enum DeviceType { pos_native_ios_phone pos_native_ipad pos_native_android_phone pos_native_android_tablet pos_browser pi_bridge } "A Device — the PHYSICAL hardware identity (native POS apps, the in-Office browser POS, the Pi legacy-peripheral bridge), kept separate from the logical Register it serves: the pairing ref is ONE-WAY Device→Register (0..1, re-pairable — registerId lives HERE, never on the Register). Born pending_pairing via the BESPOKE enrollDevice (the pairing code returns ONCE, TTL 15 min); completePairingDevice (PUBLIC — the code IS the auth) flips it active and returns the device credential ONCE (hash-only at rest; mandatory 12-month rotation, decision I). active ⇄ suspended is the kill-switch pair; dooms from active/suspended gate on the paired Register's open TillSession. At POS the REAL principal is COMPOSITE (decision E): device session (WHERE/trust) + user session (WHO/authority) — the auth seam. NOT searchable (infrastructure — the Register non-joiner stance)." type Device { id: ID! "The group-scoped human-facing system id (DE-…)." sysId: String! type: String! caption: String! "The FSM state: pending_pairing | active | suspended | doomed." status: String! "The parent LogicalFacility; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned hardware class — set at enrollment, IMMUTABLE." deviceType: DeviceType! "The 0..1 ONE-WAY Register pairing. Moves ONLY via pairDeviceToRegister/unpairDevice — never via update." registerId: ID "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the devices listing — the records + the opaque resume cursor." type DevicePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Device!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for a Device. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). deviceType and the parent LF are IMMUTABLE at birth; registerId moves ONLY via pairDeviceToRegister/unpairDevice (an evented operational act, never a field edit); status moves ONLY via the transition ops." input EditDeviceInput { caption: String code: String } "A peripheral class. The scale serves catch-weight; the card_reader is the Stripe Terminal hook." enum DevicePeripheralType { barcode_scanner receipt_printer label_printer display_pole cash_drawer card_reader scale } "A peripheral connection mode: native USB/Bluetooth, the Pi legacy gateway, Chrome WebUSB, or network (LAN-attached Stripe smart readers — the Terminal server lanes)." enum DevicePeripheralConnection { native_usb native_bluetooth pi_bridge webusb network } "One preset peripheral model." type PeripheralModel { "The stable registry key a DevicePeripheral’s model references." model: String! "The display name (the peripheral’s natural default caption)." caption: String! peripheralType: DevicePeripheralType! "The connection modes this model supports — a DevicePeripheral must use one of these." connections: [DevicePeripheralConnection!]! } "A DevicePeripheral — the hardware a Device OWNS: barcode scanners, receipt/label printers, display poles, cash drawers, card readers, and scales. The model MUST name the AT-maintained preset registry (cannedPeripheralModels, registry v2 — merchants pick supported models, never author drivers); peripheralType + model are IMMUTABLE at birth (swapped hardware = a new peripheral), connection is mutable (re-cabling is an edit). NOT searchable (hardware config — reached via its owning Device)." type DevicePeripheral { id: ID! "The group-scoped human-facing system id (PH-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Device; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned peripheral class — set at creation, IMMUTABLE." peripheralType: DevicePeripheralType! "The preset-registry model key (the preset series — cannedPeripheralModels lists the roster) — set at creation, IMMUTABLE." model: String! "How this unit attaches — mutable; must stay within the model’s supported set (kit-gated)." connection: DevicePeripheralConnection! "The Stripe Terminal reader this unit registered as: present exactly on card_reader+network peripherals (stamped at birth); IMMUTABLE. A tmr_ reference of at most 128 characters — it rides record-first into Payment.methodRef." readerRef: String } "One page of the devicePeripherals listing — the records + the opaque resume cursor." type DevicePeripheralPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [DevicePeripheral!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a DevicePeripheral. The tenant is derived SERVER-SIDE; deviceId (the parent — rides the header) is tenant-scoped + non-doomed server-side (provisioning precedes pairing — pending_pairing/active/suspended all accept peripherals); model/type/connection coherence validates against the preset registry at the boundary AND in the kit." input NewDevicePeripheralInput { "Optional: when omitted the per-type default applies — the preset model's display name ('Zebra DS2208'); when supplied it must be non-blank." caption: String "The owning Device — tenant-scoped + non-doomed. Immutable after birth." deviceId: ID! "Immutable after birth." peripheralType: DevicePeripheralType! "A preset-registry key (cannedPeripheralModels) whose peripheralType matches. Immutable after birth." model: String! "One of the model’s supported modes." connection: DevicePeripheralConnection! "The reader-displayed Stripe registration code — REQUIRED iff card_reader+network (the smart reader registers at birth, on the org’s connected account), REFUSED otherwise (strict both ways). Consumed by Stripe — never stored." registrationCode: String } "Edit-input for a DevicePeripheral. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). peripheralType/model and the parent Device are IMMUTABLE at birth (swapped hardware = a new peripheral); a connection edit re-validates against the stored model’s supported set in the kit; status moves ONLY via the transition ops." input EditDevicePeripheralInput { caption: String "One of the model’s supported modes (kit-gated)." connection: DevicePeripheralConnection } "An ApiKey — the third-party / programmatic access credential. Issued ONLY by an org-group-level OWNER (the engine's LIVE ownership gate — the minting actor is a User whose Account holds group ownership); parent = the minting User. REACH DERIVES LIVE from the minter's CURRENT ownerships — the key works on exactly the group's orgs where the minter is also currently an org owner; ownership loss/re-grant is never a transition (re-grant REVIVES a not-doomed key). Descriptors ride the Roles grammar (allow/disallow, default-deny, disallow-wins), IMMUTABLE at birth; mandatory expiry ≤ 12 months (the scheduler fires active → expired — a DISTINCT doomed terminal). The secret shows ONCE at mintApiKey, hash-only at rest, and is presented only to exchangeApiKey → a 24 h-absolute no-idle API session. NOT searchable; the reads are -gated (integration config, off the floor)." type ApiKey { id: ID! "The group-scoped human-facing system id (AK-…)." sysId: String! type: String! caption: String! "The FSM state: active | expired | doomed." status: String! "The parent = the MINTING User; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The allow/disallow descriptor set — set at minting, IMMUTABLE." descriptors: [RoleDescriptor!]! "The mandatory expiry instant; the scheduler fires active → expired at this date." expiresAt: String! } "One page of the apiKeys listing — the records + the opaque resume cursor." type ApiKeyPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ApiKey!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Edit-input for a ApiKey. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). CAPTION ONLY: descriptors + expiresAt are IMMUTABLE at birth (a silently-widening key is the exact drift forbids — a different scope/life is a NEW key + a doom of the old); status moves ONLY via doomApiKey / the scheduled expiry." input EditApiKeyInput { caption: String } "One author-time step mark." type ScratchpadStepMark { "The mark vocabulary: UNKNOWN_OPERATION | NOT_CREATE_CLASS | INVALID_JSON | INPUT_TOO_LONG | INPUT_INVALID | BAD_STEP_REF." code: String! message: String! } "One plan step. input is the operation's input-argument JSON as TEXT (the revisions recordJson carrier class — no generic JSON scalar exists); realizedId + bornType stamp TOGETHER once realization executes this step (the forward provenance — realizedInto; the Task {type,id} row shape)." type ScratchpadPlanStep { seq: Int! operation: String! input: String! mark: ScratchpadStepMark realizedId: ID bornType: String } "The transitionScratchpad op vocabulary." enum ScratchpadTransitionOp { "draft → ready." ready "ready → draft." reopen "ready → approved." approve "draft → abandoned · ready → abandoned · approved → abandoned · realization_failed → abandoned." abandon } "A Scratchpad: collects intent (free text now; wizard answers/imports/suggestions/consultations mint through their own entrances later) until it holds a PLAN — ordered {operation, input} steps in wire vocabulary (≤24; creates-only v1: each operation must be a live create-class registry mutation) — and, once a human approves, REALIZES the plan into born constructs through the ordinary ops under the realizing caller's OWN session and capability (the hardened-Aldric law: the spine holds ZERO special authority; AI is just one plan author, and the spine never knows the difference). USER-parented (the collector owns the walk), group-rooted. Invalid steps are MARKED, never repaired; a marked plan can be ready for human eyes but can never be approved. Approval PINS the plan revision (the approved plan IS the executed plan); realization is idempotent + convergent-resume (the realized-id stamps are the idempotency keys) and every step's born cause narrates the scratchpad. The ops event domain (at.ops.scratchpad.*)." type Scratchpad { id: ID! "The group-scoped human-facing system id (SD-…)." sysId: String! type: String! caption: String! "The FSM state: draft | ready | approved | realizing | realized | realization_failed | abandoned." status: String! "The collecting User; parentId ≠ rootId by construction (the org group is the root)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "Where the plan came from (wizard | freeform | import | suggestion | consultation) — stamped at the entrance (freeform v1), never caller-editable." origin: String! "The collected free-text intent (≤8192; absent = nothing collected yet)." intent: String "The ordered plan (seq === position, server-assigned; empty until setScratchpadPlan; marks are the author-time verdicts, verbatim)." plan: [ScratchpadPlanStep!]! "Bumps on every setScratchpadPlan — the approval pin's subject." planRevision: Int! "Stamped by approve (= planRevision at approval) — realization refuses on drift (the OCC pin)." approvedPlanRevision: Int "The step currently executing (progress-honest; a resume finding it set with no realized id refuses auto-resume — the ambiguity fence)." inFlightSeq: Int "The last realization fault, superseded by a successful retry (the ChangeRequest realizationFault class)." realizationFault: String } "One page of the scratchpads listing — the records + the opaque resume cursor." type ScratchpadPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Scratchpad!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "One authored plan step." input ScratchpadPlanStepInput { "A live create-class registry mutation name (create — creates only v1, strict)." operation: String! "The operation's input-argument JSON as text (≤4096 chars)." input: String! } "Create-input for a Scratchpad. The tenant AND the parent are derived SERVER-SIDE; origin stamps freeform v1 (the suggestion/consultation entrances mint through their own engines later). ⚠ the caption IS the scratchpad name and is REQUIRED at the boundary." input NewScratchpadInput { "Optional: when omitted the per-type default applies — NONE — the CsCase divergence class: the caption IS the scratchpad name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The collected free-text intent (≤8192); omit = named before collected." intent: String } "Edit-input for a Scratchpad. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic); explicit null CLEARS intent. Caption/intent edit freely in every LIVE state — realizing and the terminal states refuse CONFLICT/IMMUTABLE mechanically; the PLAN moves ONLY via setScratchpadPlan (draft-only — the review hold freezes it). status moves ONLY via the transition ops." input EditScratchpadInput { "The scratchpad name." caption: String "The collected intent; explicit null clears." intent: String } "One drafted plan step." type SuggestionPlanStep { operation: String! input: String! } "A Suggestion: a declared SKILL's detector minted this offer from bounded live reads: the WHY in merchant words, the EVIDENCE refs (exactly what it looked at), a DRAFTED PLAN in wire vocabulary (the {operation, input} shape), and an expiry. System-minted end to end (authorless — no create/edit surface exists; refreshSuggestions is the only entrance). the offer rule: a caller sees only suggestions whose drafted plan THEIR OWN capability could realize — the list filters, the get answers null, and take/decline enforce the same predicate (preview ≡ enforcement). TAKING mints a Scratchpad through the live spine (origin suggestion; the plan lands via the setScratchpadPlan validate/mark path VERBATIM — stale steps arrive MARKED, never repaired); DECLINING stores the learning reason on the record. Every suggestion drills down to the SuggestionSchema that produced it. The ops event domain (at.ops.suggestion.*)." type Suggestion { id: ID! "The group-scoped human-facing system id (SU-…)." sysId: String! type: String! caption: String! "The FSM state: open | taken | declined | expired | superseded." status: String! "The Organization whose desk holds the offer; rootId = the org group." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The declared skill that produced this offer (low_stock | aging_approvals | stock_imbalance — the registry; a skill is declared, never emergent)." skill: String! "The per-org schema registration that generated it (the v2 drill-down — provenance to the generator)." schemaId: ID! "WHY, in merchant words (≤2000)." why: String! "Exactly what the detector looked at (the Task {type, id} structured-ref shape reused — ≤16)." evidenceRefs: [TaskConstructRef!]! "The drafted plan in wire vocabulary." draftedPlan: [SuggestionPlanStep!]! "The (skill × subject) identity (≤256) — the refresh dedup law: an identical open twin skips the mint; changed content supersedes and mints fresh." dedupKey: String! "The offer's lapse instant (mint + 7 days, ISO-8601): the sweep expires it, and a take/decline past it refuses CONFLICT/EXPIRED lazily expiring on the touch." expiresAt: String! "TAKE-stamped (with the taken flip — one fact): the Scratchpad the take minted through the live spine; the provenance forward." takenScratchpadId: ID "DECLINE-stamped (with the declined flip): the stored learning judgment." declineReason: String } "One page of the suggestions listing — the records + the opaque resume cursor." type SuggestionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Suggestion!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The transitionSuggestionSchema op vocabulary." enum SuggestionSchemaTransitionOp { "active → parked." park "parked → active." reactivate "parked → doomed." doom } "A SuggestionSchema: ONE row per (Organization × declared skill), ensure-minted lazily at the first desk refresh (authorless; the (org × skill) uniqueness marker makes the ensure race-proof). PARKING it stops the generator for the org (‘we no longer run these’ — reactivatable, owner-gated A2_STRUCTURE); DOOMING is the deliberate permanent kill (parked-first; refused CONFLICT/REFERENCED while OPEN suggestions still cite it; a doomed schema NEVER re-ensures). Every Suggestion's schemaId drills down here — provenance to the generator. The skill's declared words/watches/drafts live in the contracts SUGGESTION_SKILL_REGISTRY. The ops event domain (at.ops.suggestion_schema.*)." type SuggestionSchema { id: ID! "The group-scoped human-facing system id (SS-…)." sysId: String! type: String! caption: String! "The FSM state: active | parked | doomed." status: String! "The Organization the registration governs; rootId = the org group." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The declared skill this row registers (low_stock | aging_approvals | stock_imbalance — the caption carries the skill's merchant words)." skill: String! } "One page of the suggestionSchemas listing — the records + the opaque resume cursor." type SuggestionSchemaPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [SuggestionSchema!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One drafted step on a turn." type ConsultationPlanStep { operation: String! input: String! mark: ScratchpadStepMark } "One transcript turn (the CaseMessage thread class — sysId-less, IMMUTABLE once spoken EXCEPT the set-once takenScratchpadId stamp). seq is the conversation ordinal (0-based, server-assigned); createdAt is the transcript timestamp." type ConsultationTurn { id: ID! seq: Int! role: String! body: String! materialIds: [ID!] draftedPlan: [ConsultationPlanStep!] takenScratchpadId: ID createdAt: String! } "The askConsultation result — the updated record + the two turns the ask appended (the question as spoken, the reply as drafted-and-marked)." type AskConsultationResult { consultation: Consultation! turns: [ConsultationTurn!]! } "The transitionConsultation op vocabulary." enum ConsultationTransitionOp { "open → archived." archive "archived → open." reopen "open → discarded · archived → discarded." discard } "A Consultation: the VERBATIM TRANSCRIPT is the record (bounded turn rows — read via consultationTurns) and the MEMORY is the STORED rolling summary ON this record — auditable, purgeable, merchant-visible, never hidden model state. Each ask composes the summary + the last 12 turns verbatim + the asked materials' STORED extractions (EXTRACT-THEN-COMPOSE — raw content is read exactly once, at material confirm). Aldric may attach a DRAFTED PLAN to a reply; TAKING a drafted plan (takeConsultationPlan) mints a Scratchpad through the live spine (origin consultation) and the walk proceeds under the TAKER's own capability (the hardened-Aldric law — the chat holds ZERO mutation authority). Outgrowing the 200-turn transcript refuses HONESTLY naming the cure: a follow-on consultation linked via followOnOfId (never silent middle-loss). USER-parented (the consulter owns the chat), group-rooted. The ops event domain (at.ops.consultation.*)." type Consultation { id: ID! "The group-scoped human-facing system id (CI-…)." sysId: String! type: String! caption: String! "The FSM state: open | archived | discarded." status: String! "The consulting User; parentId ≠ rootId by construction (the org group is the root)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The transcript length (== the next turn's seq; the turn rows are the truth, this is the OCC-stamped cache)." turnCount: Int! "THE STORED ROLLING SUMMARY." summary: String "Turns below this seq live INSIDE the summary; turns from it onward compose verbatim into each ask." summarizedThroughSeq: Int! "The outgrowth link — the consultation THIS one continues." followOnOfId: ID "SYSTEM-stamped at birth, at every ask and at reopen = the last activity + 30 days — the scheduler archives the conversation at this instant if it is still open; a parked row keeps its last stamp as history." idleArchiveAt: String "SYSTEM-stamped when the conversation archives (by you or by the idle sweep) = the archive instant + 90 days — the scheduler moves the transcript to the archive bucket at this instant if the conversation is still archived; reopen removes it; a tiered row carries none." turnsTierAt: String "Present (`archive`) once the transcript has moved to the archive bucket after 90 days archived — consultationTurns still reads it whole (the tier is transparent); taking a drafted plan then needs a reopen first; reopen brings the rows back and clears this. Absent while the rows are hot." turnsTier: String } "One page of the consultations listing — the records + the opaque resume cursor." type ConsultationPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Consultation!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Consultation. followOnOfId must name an in-tenant Consultation (the outgrowth link — its stored summary is YOURS to paste into the first ask; the platform never copies context silently). The tenant AND the parent derive SERVER-SIDE." input NewConsultationInput { "Optional: when omitted the per-type default applies — NONE — the Scratchpad divergence class: the caption IS the consultation name, and an omitted caption refuses VALIDATION/INVALID at the boundary instead of defaulting; when supplied it must be non-blank." caption: String "The consultation this one continues (in-tenant gated; optional)." followOnOfId: ID } "Edit-input for a Consultation. Every field optional, at least ONE required; supplied fields REPLACE — the caption ONLY (the transcript, summary, and counters are engine-owned facts that never move by edit); open only (archived and discarded refuse CONFLICT/IMMUTABLE mechanically — reopen first)." input EditConsultationInput { "The consultation name." caption: String } "A WebhookSubscription — the documented non-GraphQL edge OUT (mirrors the inbound Stripe webhook edge): the merchant registers an https target URL + a filtered set event names (the DERIVED deliverable universe — transition success events + per-construct birth names; enumerate it via the integrator docs), and the delivery lane POSTs HMAC-signed THIN payloads at-least-once with retries/backoff/DLQ. The payload names {id, event, occurredAt, construct{type,id}, revision, subscriptionId} — the receiver dedupes on id and READS the record through this SAME API with its ApiKey (no fat payloads, no parallel surface). Signing mirrors the Stripe scheme (almondtill-signature: t=,v1=. under the secret>); the secret shows ONCE at create/rotate and lives in the non-streamed credential store, never on the record. GROUP-parented (parentId === rootId); born active; 20 consecutive delivery failures fire the automatic active → suspended flip (system:repeated_delivery_failure — the deliverer, never a caller); reactivate serves both inactive → active and suspended → active (fix the endpoint, then reactivate; missed events do NOT replay — re-sync via the API). Owner-gated end to end (the mintApiKey posture); NOT searchable (integration config — reached via the owner-gated list)." type WebhookSubscription { id: ID! "The group-scoped human-facing system id (WH-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | suspended | doomed." status: String! "The parent = the org GROUP (the parent-is-the-org-group clause); parentId === rootId always (the Affiliate class — deliveries span the whole group’s orgs)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The https delivery endpoint (the egress law: https only, no credentials, no explicit port, no IP-literal/localhost/private-suffix hosts; ≤512 chars). Mutable via update — fixing the endpoint is the suspended-repair flow." targetUrl: String! "The event-name filter set (1..64, deduped) — each name must be in the DERIVED deliverable universe (transition success events + at...create.ok.v1 birth names over the whole construct catalog)." eventTypes: [String!]! "Consecutive delivery-attempt failures (the deliverer’s counter — reset by the first success after failures; NEVER written on steady-state success). At 20 the automatic suspend fires." consecutiveFailures: Int! "The last failed delivery attempt’s instant (failure-path-only; stands as history after recovery until the next failure overwrites)." lastFailureAt: String "The last failure’s short token — an HTTP status (http_500) or a fetch-error class (timeout, network); never a response body." lastFailureCode: String "Stamped by the automatic suspend flip; cleared by reactivate." suspendedAt: String "The last signing-secret rotation’s instant; null until the first rotation." secretRotatedAt: String "The owning Plugin (optional): this subscription is part of that plugin’s declared event feed; IMMUTABLE at birth (a re-bind = a new subscription); an un-doomed bound subscription blocks the plugin’s doom." pluginId: ID } "Edit-input for a WebhookSubscription. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). caption/targetUrl/eventTypes are all mutable (a URL move or a re-filtered set is normal lifecycle — the contrast with the ApiKey’s immutable descriptors: a subscription carries no authority, only routing; suspended rows stay editable — fix the URL, then reactivate); status moves ONLY via the FSM ops; the failure counters move ONLY in the deliverer; the secret moves ONLY via rotateWebhookSubscriptionSecret." input EditWebhookSubscriptionInput { caption: String targetUrl: String eventTypes: [String!] } "A Plugin — a third-party extension's DECLARATION record on the canned-pool selection pattern: the group registers the plugin ONCE, each org ENABLES it via an OrgPlugin selection. Extensions run OUT-OF-PROCESS on the developer's own infrastructure — never in-process here. The record declares what the integration IS: the least-privilege descriptor scopes (the ApiKey grammar, allow-only — the CONTRACT the merchant mints a key against; descriptive at v1, the marketplace's automated mint-flow consumes it later), an optional bound ApiKey identity (validated live in-group at write; informational v1), and its event feed — which rides REAL WebhookSubscription rows carrying pluginId (never a mirrored field). uiSlots is deliberately ABSENT until the office slot system exists (the staged-realization boundary, map d.11). ≤64 per group; doom is gate-protected: a non-doomed OrgPlugin selection OR an un-doomed bound WebhookSubscription blocks it. NOT searchable (integration config)." type Plugin { id: ID! "The group-scoped human-facing system id (PN-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent = the org GROUP (the selection-master law); parentId === rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The developer/publisher display name (informational — the marketplace listing byline seed)." developerName: String "The developer homepage (https by shape; informational — NOT a delivery target: the egress law lives on WebhookSubscription.targetUrl alone)." homepageUrl: String "The declared least-privilege scope set (the ApiKey grammar rows, ALLOW-only, deduped; 0..800 — a webhook-only plugin legally declares none). Descriptive v1; editable BY DESIGN (a declaration carries no authority — the disclosed ApiKey-immutability contrast)." requiredScopes: [RoleDescriptor!]! "The bound ApiKey identity (optional; validated live in-group at write). Informational v1 — no doom-gate retrofits onto the LIVE ApiKey FSM." apiKeyId: ID } "One page of the plugins listing — the records + the opaque resume cursor." type PluginPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Plugin!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for a Plugin declaration. The tenant (org group) is derived SERVER-SIDE from the principal; an apiKeyId, when supplied, is tenant-scoped + un-doomed server-side (STRICT)." input NewPluginInput { "Optional: when omitted the per-type default applies — 'plugin by ' when given, else 'plugin'; when supplied it must be non-blank." caption: String developerName: String homepageUrl: String "The declared allow-only scope set; omitted = none (a webhook-only plugin)." requiredScopes: [RoleDescriptorInput!] apiKeyId: ID } "Edit-input for a Plugin. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). Everything is editable BY DESIGN v1 (the declaration carries no authority — the disclosed ApiKey contrast); status moves ONLY via the FSM ops." input EditPluginInput { caption: String developerName: String homepageUrl: String requiredScopes: [RoleDescriptorInput!] apiKeyId: ID } "An OrgPlugin selection — the per-org ENABLEMENT of a group Plugin. Parent = the ORGANIZATION (not the family root). Freely deactivatable/doomable; a NON-doomed selection blocks the master Plugin doom only. CONFLICT/UNSELECTED is reserved for future org-scoped plugin references (none exist v1 — the enablement itself is the v1 product)." type OrgPlugin { id: ID! "The group-scoped human-facing system id (EP-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent Organization; for a selection parentId!== rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The selected group Plugin — set at creation, IMMUTABLE thereafter." pluginId: ID! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the orgPlugins listing — the records + the opaque resume cursor." type OrgPluginPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [OrgPlugin!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for an OrgPlugin selection. The tenant (org group) is derived SERVER-SIDE from the principal; organizationId (the parent org) and pluginId are tenant-scoped server-side and must be active (STRICT)." input NewOrgPluginInput { "Optional: when omitted the per-type default applies — the merchant code when given, else 'Org Plugin'; when supplied it must be non-blank." caption: String "The parent Organization id — rides the header." organizationId: ID! "The group Plugin this selection enables — immutable after birth." pluginId: ID! code: String } "Edit-input for a OrgPlugin. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). pluginId is NOT editable (immutable at birth, the selection IS the (org × master) edge; re-pointing = recreate), nor is the parent-org ref (the header)." input EditOrgPluginInput { caption: String code: String } "Delivery is PULL ONLY v1: list runs via feedSubscriptionRuns, then mint a short-lived presigned download with mintFeedRunDownload — the BI tool authenticates as its OWN ApiKey session and there are ZERO stored credentials (the presigned ticket IS the custody; a push feed-ready event is a named growth). ⚠ THE PER-ORG WELD: organizationId names the ONE exported org (in-group live-gated); org-parented dataset rows filter to it, GROUP-parented catalog masters (Style/Product) export whole — the shared catalog IS each org's catalog. GROUP-parented (parentId === rootId); born active with nextDueAt = the birth instant (the next hourly tick runs it); at most 10 ACTIVE feeds per group (the webhook cap class); 5 consecutive FAILED RUNS fire the automatic active → suspended flip (system:repeated_delivery_failure — the exporter, never a caller); reactivate serves both inactive → active and suspended → active (fix the feed via update, then reactivate; no catch-up runs — the next run is the next cadence step). Runs prune to the newest 8 per feed (bounded custody). Owner-gated end to end (the mintApiKey posture — data-OUT is exfiltration-adjacent); NOT searchable (integration config — reached via the owner-gated list)." type FeedSubscription { id: ID! "The group-scoped human-facing system id (FD-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | suspended | doomed." status: String! "The parent = the org GROUP (the org-group clause); parentId === rootId always (the WebhookSubscription class — the feed ROW is group custody; the EXPORTED SLICE is the organizationId org, the per-org law)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "THE PER-ORG WELD: the ONE org this feed exports — must be an in-group live Organization (gated at create AND edit); org-parented dataset rows filter to it; group-parented catalog masters export whole (the shared catalog IS each org’s catalog)." organizationId: ID! "WHAT exports — one canned construct type (OrgCustomer · Style · Product · OrgVendor · Order — the two-layer law: the roster IS the vocabulary; InventoryEntry and the event-lake extracts are named growths). Mutable (routing, not authority)." dataset: String! "HOW OFTEN — daily · weekly · monthly. nextDueAt steps by the cadence from each RUN instant (a late run does not compound); a cadence edit applies from the NEXT run (the stored due stands)." cadence: String! "The file serialization — jsonl (one stored record per line, storage attrs stripped; lossless, the default posture) or csv (the flat scalar fields, header = the union; nested fields omitted — the disclosed lossy trade for flat masters)." format: String! "WHEN the next run is due (STORED — the hourly sweeper compares against it, never re-derives from history; birth = the create instant, so the first tick runs it)." nextDueAt: String! "The last successful run’s instant (null until the first success)." lastRunAt: String "The last successful run’s object key under the group’s feeds/ prefix (the newest pull coordinate; feedSubscriptionRuns lists the retained window)." lastRunKey: String "Consecutive FAILED runs (the exporter’s counter — reset by the first success after failures). At 5 the automatic suspend fires." consecutiveFailures: Int! "The last failed run’s instant (failure-path-only; stands as history after recovery until the next failure overwrites)." lastFailureAt: String "The last failure’s short named token (rows_over_cap · serialize_fault · s3_fault); never row data." lastFailureCode: String "Stamped by the automatic suspend flip; cleared by reactivate." suspendedAt: String } "Edit-input for a FeedSubscription. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). caption/organizationId/dataset/cadence/format are all mutable (a re-pointed feed is normal lifecycle — the WebhookSubscription routing-not-authority contrast; suspended rows stay editable — fix the feed, then reactivate; organizationId re-gates in-group live). status moves ONLY via the FSM ops; the run stamps + counters move ONLY in the exporter; a cadence edit applies from the NEXT run (nextDueAt stands)." input EditFeedSubscriptionInput { caption: String organizationId: ID dataset: String cadence: String format: String } "A FraudAlert — the merchant TRIAGE register over the derived fraud-signal layer: a signal crossing a policy threshold raises an alert naming the signal family (void_no_sale · return_refund_abuse · discount_override_abuse · override_pattern · cash_over_short · dispute_chargeback), the normalized score (0..100) vs the crossed threshold, the implicated staff principal and/or facility, the scoring window, and the triggering records. SIGNALS, NOT ENFORCEMENT: the / authority layer enforces; an alert only records and asks. SYSTEM-RAISED end to end — no create surface exists; the merchant triages: acknowledge (open → acknowledged — investigating; disarms the age-out), then confirm (a KEPT immutable finding — terminal but NOT doomed) or dismiss (a false positive — the reason is REQUIRED). Untriaged alerts age out after 30 days (open → expired, the scheduled lane). Triage identity/notes are the revision causes (History + the org-bus render actor + reason + instant — never duplicated fields). NOT searchable (sensitive review data — reached via the A17_FRAUD-gated paginated listing, never name-found); the listing pages NEWEST-first and drops doomed (dismissed/expired) per the - law while confirmed findings stay listed." type FraudAlert { id: ID! "The group-scoped human-facing system id (FA-…)." sysId: String! type: String! caption: String! "The FSM state: open | acknowledged | confirmed | dismissed | expired." status: String! "The parent = the org GROUP; parentId === rootId always (the WebhookSubscription class — the register is group custody)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "WHICH derived-signal family fired (void_no_sale · return_refund_abuse · discount_override_abuse · override_pattern · cash_over_short · dispute_chargeback — the two-layer law: the canon's six, membership IS the vocabulary)." signalKind: String! "The scorer's normalized score for the window (0..100)." score: Int! "The policy bound the score crossed (the same scale — v1 canned consts; the policy layer composes real merchant thresholds later, disclosed)." threshold: Int! "The scorer's bounded human explanation (≤500) — never raw event data." reason: String! "The scoring window — a UTC month (YYYY-MM) or day (YYYY-MM-DD); the scorer picks the grain per signal kind." periodKey: String! "The implicated staff principal (scored per cashier); in-group-gated at raise, ANY status (the review judges PAST conduct); null when the signal implicates a facility/period only." implicatedUserId: ID "The implicated facility (scored per LF); in-group-gated at raise; null when the signal implicates a person/period only." logicalFacilityId: ID "The triggering records (≤20 — the Task {type, id} structured-ref shape reused, the Suggestion evidenceRefs precedent): advisory evidence the scorer derived from the lake; nothing gates on them, a purged target renders as a tombstone." constructRefs: [TaskConstructRef!]! "WHEN an untriaged (open) alert ages out (raise + 30 days — the scheduled lane fires open → expired; acknowledging disarms it)." expiresAt: String! } "One page of the fraudAlerts listing — the records + the opaque resume cursor." type FraudAlertPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [FraudAlert!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "A PrivacyRequest — the GDPR/CCPA REQUEST REGISTER: every data-subject request RECEIVED (erasure · access · portability · rectification · opt_out) is recorded with full provenance — the regime (gdpr · ccpa), the arrival channel, the received instant, and the SUBJECT (a known Consumer ref OR an inline subjectRef handle — at least one; the register necessarily holds this identity: ⚠ IT IS THE ERASURE-SUPPRESSION LIST, governing any later archive download/use). The ladder: verify (the identity gate — v1 the verifier's assertion, the proof narrative on the revision cause) → start → fulfill (the BESPOKE system-edge driver: the affected records link back refs — provable WHICH request drove WHICH scrubbing; an evidence-less fulfill refuses CONFLICT/INCOMPLETE, retryable); reject serves received AND verified (ONE op, two edges — the reason is REQUIRED: a refused privacy request states its grounds). THE FULFILLMENT MECHANICS STAY THE EXISTING OPS (erasure = the live eraseConsumer [the Consumer doomed = de-identified terminal]; access/portability per-subject export = a named growth; rectification/opt-out = ordinary edits/consent ops) — the register RECORDS and LINKS, it never executes. NOT searchable (a compliance register holding subject PII — the -gated paginated listing); the listing pages NEWEST-first; rejected drops per page as doomed while fulfilled records stay listed." type PrivacyRequest { id: ID! "The group-scoped human-facing system id (PV-…)." sysId: String! type: String! caption: String! "The FSM state: received | verified | in_progress | fulfilled | rejected." status: String! "The parent = the org GROUP; parentId === rootId always (the FraudAlert class — the register is group custody)." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "WHICH data-subject right (erasure · access · portability · rectification · opt_out — the canon's five; canned). IMMUTABLE at birth (a changed ask is a fresh request)." requestType: String! "WHICH regime (gdpr · ccpa — EU/CA first, extensible deliberately). IMMUTABLE at birth." regime: String! "HOW it arrived (email · phone · in_store · web · mail). IMMUTABLE at birth." channel: String! "WHEN it arrived (may predate the recording; omitted at create ⇒ the create instant, stamped engine-side)." receivedAt: String! "The known subject; null for inline/guest subjects." consumerId: ID "The inline/guest subject handle (the requester's stated email/name, ≤200) — REQUIRED when consumerId is absent (at least one of the two names the subject)." subjectRef: String "The fulfillment evidence (≤20 — the {type, id} structured-ref shape reused): EMPTY at birth, stamped by fulfillPrivacyRequest (the de-identified Consumer, the export target, the rectified records); advisory + tombstone-tolerant." affectedRefs: [TaskConstructRef!]! } "One page of the privacyRequests listing — the records + the opaque resume cursor." type PrivacyRequestPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PrivacyRequest!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for a PrivacyRequest. The subject names via consumerId (in-group, ANY status — the register records reality) OR subjectRef (the inline handle) — at least one; receivedAt omitted ⇒ the create instant." input NewPrivacyRequestInput { "Optional: when omitted the per-type default applies — ' request ()' — the right + the regime name the request; when supplied it must be non-blank." caption: String "erasure · access · portability · rectification · opt_out." requestType: String! "gdpr · ccpa." regime: String! "email · phone · in_store · web · mail." channel: String! "Optional ISO arrival instant; omitted ⇒ now." receivedAt: String "The known subject — an in-group live Consumer (gated)." consumerId: ID "The inline/guest subject handle — required when consumerId is absent." subjectRef: String } "The EFFECTIVE resolved policy value for one (scope × key) at one instant: the WINNING nearest-ancestor record's identity + window, or the registry-default floor (source = default, record fields null). Resolution NEVER misses." type PolicyResolution { "The registry key resolved." key: String! "The effective value." valueInt: Int! "Where the answer came from: record (a covering window won) | default (the registry floor)." source: String! "The winning PolicyValueRecord — null when source = default." recordId: ID "The winning record's level (org | lf) — null when source = default." level: String "The winning record's window — null when source = default." startAt: String endAt: String } "A PolicyValueRecord — ONE effective-dated value window in the tenant POLICY schedule, resolved LF → org → the registry default NEAREST-ANCESTOR-WITH-VALUE at every read. Keys are REGISTRY-DEFINED (appointment.lead_time_minutes · appointment.max_advance_days · appointment.no_show_window_minutes · appointment.overbook_allowed · fraud.threshold.cash_over_short · fraud.threshold.discount_override_abuse · fraud.threshold.dispute_chargeback · fraud.threshold.override_pattern · fraud.threshold.return_refund_abuse · fraud.threshold.void_no_sale · training.score_visibility — an unknown key refuses naming the roster; v1 = the fraud-alert thresholds, one per signal kind, default 0 on the 0..100 score scale; future keys join by registry row). Doom cancels a not-yet-effective FUTURE record only (CONFLICT/IMMUTABLE otherwise — supersede instead). The window/key/value fields are wire-IMMUTABLE (the edit surface is caption only). ⚠ The catalog ladder's zone rung is a NAMED registry growth — no v1 key legally scopes there." type PolicyValueRecord { id: ID! "The group-scoped human-facing system id (PC-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The scope anchor: an Organization or a LogicalFacility — validated live at create; rootId = the org group." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The resolution level this record binds (org | lf — most-specific-wins). Stored explicit, validated against the REAL parent at create; IMMUTABLE." level: String! "The registry key. IMMUTABLE — a different key is a different sub-schedule." key: String! "The value (INT — the no-floats discipline; registry-bounded per key: the v1 thresholds take 1..100). IMMUTABLE — supersede with a new window." valueInt: Int! "The window start (INCLUSIVE; UTC ISO-8601) — set at birth (absent in the create input = effective NOW, server-stamped), IMMUTABLE thereafter." startAt: String! "The window end (EXCLUSIVE; UTC ISO-8601; ALWAYS present — far-future = the standing value). Moves ONLY via the system splice trim." endAt: String! } "One page of the policyValues listing — the records + the opaque resume cursor." type PolicyValueRecordPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [PolicyValueRecord!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for a PolicyValueRecord. The tenant (org group) is derived SERVER-SIDE from the principal; the LEVEL is named by the anchor field: organizationId = an org-level value, logicalFacilityId = an LF override — EXACTLY ONE (no group level exists; the registry default is the floor above org). The anchor is tenant-scoped server-side and must be ACTIVE; the key must be registry-defined and the value inside its bounds; startAt is optional (absent = effective NOW, server-stamped; explicit values must be >= the server now — no past starts) and must precede endAt." input NewPolicyValueRecordInput { "Optional: when omitted the per-type default applies — the window coordinate ` = from `; when supplied it must be non-blank." caption: String "The org anchor for an ORG-level value — tenant-scoped server-side; exactly one of the two anchors." organizationId: ID "The LF anchor for an LF-level override — tenant-scoped server-side; never together with organizationId." logicalFacilityId: ID "The registry key — an unknown key refuses naming the roster." key: String! "The value — INT, registry-bounded per key (the v1 thresholds take 1..100)." valueInt: Int! "The window start (INCLUSIVE; UTC ISO-8601). Optional — absent = effective NOW (server-stamped); explicit values must be >= the server now (no past starts)." startAt: String "The window end (EXCLUSIVE; UTC ISO-8601). ALWAYS required (far-future = the standing value); must be strictly after startAt." endAt: String! } "Edit-input for a PolicyValueRecord. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). The window/key/value fields are NOT editable (wire-IMMUTABLE facts, the surface verbatim — supersede with a new window or doom a FUTURE record and re-create; the system splice trim is the ONE sanctioned endAt move)." input EditPolicyValueRecordInput { caption: String } "A CouponBatch: a Coupon-parented batch of UNIQUE SINGLE-USE child codes (the campaign lane). Each child code is a KEY to the PARENT coupon's terms — the parent's flavor/window/cap/eligibility verdicts run UNCHANGED at attach and the parent's REDEEM counter counts every use; the child adds exactly ONE law: it redeems ONCE (the stamp rides the PLACE transaction conditioned — a lost race between two carts refuses the second placement). Minted WHOLE in ONE transaction (≤48 codes — the ceiling IS the transaction bound; bigger campaigns mint more batches) via the bespoke createCouponBatch; the codes are SERVER-GENERATED (- — unguessable, never caller-supplied), take the SAME org-group code-namespace UNIQ marker parent codes use, and are LISTABLE via couponBatchCodes (campaign codes are distribution artifacts, not secrets). Dooming the batch VOIDS its unredeemed children (attach refuses naming the batch) while redeemed history stands; a clawed-back child (a cancelled order) is REDEEMABLE AGAIN — the customer's code survives a voided sale." type CouponBatch { id: ID! "The group-scoped human-facing system id (CB-…)." sysId: String! type: String! caption: String! "The FSM state: active | doomed." status: String! "The parent Coupon whose terms every child unlocks — IMMUTABLE at birth (re-parent = a new batch); parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The NORMALIZED prefix every child code carries (`-`) — IMMUTABLE at birth." codePrefix: String! "The minted child count (1..48 — the one-transaction bound); IMMUTABLE (the batch is born whole)." codeCount: Int! } "One page of the couponBatches listing — the records + the opaque resume cursor." type CouponBatchPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [CouponBatch!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The segment kinds (IMMUTABLE at birth) — static = explicit membership via the member ops; dynamic = membership DERIVED from the stored predicate (refreshSegment re-materializes)." enum SegmentType { static dynamic } "The loyalty-tier axis — the program NAMED (a group can run several); tier NAMES from that program's declared ladder, OR within the list." type SegmentLoyaltyTierAxis { programId: ID! tierNames: [String!]! } "The purchase axis' monetary floor." type SegmentPurchaseMonetaryFloor { currency: String! minorUnits: Int! } "The purchase-history RFM axis: the supplied inner facts AND-compose; each optional, at least one present; a consumer who never COMPLETED a purchase never matches. v1 figures are completions-only gross." type SegmentPurchaseAxis { "Last completed purchase within the past N days of the refresh clock (1..3650; instant math — N × 24 h)." recencyWithinDays: Int "Lifetime completed-order count at least N (1..1,000,000)." frequencyAtLeast: Int "Lifetime completed spend in the NAMED currency at least the floor." monetaryAtLeast: SegmentPurchaseMonetaryFloor } "The dynamic-membership rule — AND across supplied axes, OR within an axis; a consumer missing an axis' fact never matches it; exclusions subtract after matching. All seven ratified axes are live (the tag axis joined with Consumer tag attachment)." type SegmentPredicate { "Match ANY listed interest against the consumer's interests (trim+case-fold equality)." interests: [String!] "Match an ACTIVE loyalty membership of the named program at ANY listed tier." loyaltyTier: SegmentLoyaltyTierAxis "Match a GRANTED consent for ANY listed purpose (withdrawn never matches)." consentPurposeIds: [ID!] "Match the consumer's preferred store (favorite LogicalFacility) in the list." preferredLogicalFacilityIds: [ID!] "Match a birthday (month-day of dateOfBirth) within the NEXT N days of the refresh clock (1..366; today counts; Feb-29 celebrates Mar-1 in non-leap years)." birthdayWithinDays: Int "Match purchase history (RFM — the completions-fed stats read-model): the inner facts AND-compose; a consumer with no completed purchase never matches." purchase: SegmentPurchaseAxis "Match a consumer carrying ANY listed Tag (the staff-curated attachment set on the Consumer); an untagged consumer never matches." tagIds: [ID!] } "A Segment: a merchant-authored CONSUMER grouping for marketing. segmentType is IMMUTABLE at birth — static (explicit membership: batched adds/removes of ≤48 consumers per call, the one-transaction law; the pair key dedupes structurally) or dynamic (membership DERIVED from the stored predicate — the member ops refuse; edit the predicate/exclusions and call refreshSegment to re-materialize; evaluatedAt shows the staleness honestly, refreshProblem words a queued refresh that could not complete, and a scheduled sweep re-refreshes stale ACTIVE dynamics ~daily). memberCount meters live membership (bounded ≤100000 — the add/refresh refuses past it naming the figure). MARKETING-ONLY-OVER-CONSENTED is the CONSUMING lane's law when campaigns/exports arrive — the definition stores membership only. NOT searchable (a membership register); inactive = staging (membership edits stay legal while building)." type Segment { id: ID! "The group-scoped human-facing system id (SE-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Segment parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "static | dynamic — IMMUTABLE at birth (a different kind is a NEW segment)." segmentType: SegmentType! "The live membership meter (the counter twin of the member rows); absent = never added." memberCount: Int "The dynamic rule (dynamic-only; AND across supplied axes, OR within one) — membership re-materializes at refreshSegment." predicate: SegmentPredicate "Manual exclusions (dynamic-only; at most 256, unique, write-time-validated Consumer refs) — subtracted AFTER matching at every refresh." excludedConsumerIds: [ID!] "The last refresh instant (dynamic-only; absent = never refreshed — honest staleness)." evaluatedAt: String "The async lane’s honest-failure word: why the last QUEUED refresh could not complete (figures named); cleared by any successful refresh; absent = clean." refreshProblem: String } "One page of the segments listing — the records + the opaque resume cursor." type SegmentPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Segment!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "The loyalty-tier axis input — tierNames must be tiers the named program DECLARES (unknown names refuse teaching the ladder)." input SegmentLoyaltyTierAxisInput { programId: ID! tierNames: [String!]! } "The monetary floor input — currency + integer minor units, both required (the floor rides whole or not at all)." input SegmentPurchaseMonetaryFloorInput { currency: String! minorUnits: Int! } "The purchase-history RFM axis input — each inner fact optional, ≥1 present; the facts AND-compose." input SegmentPurchaseAxisInput { recencyWithinDays: Int frequencyAtLeast: Int monetaryAtLeast: SegmentPurchaseMonetaryFloorInput } "The dynamic rule input — ≥1 axis, unique members per list; every ref in-tenant + active at write." input SegmentPredicateInput { interests: [String!] loyaltyTier: SegmentLoyaltyTierAxisInput consentPurposeIds: [ID!] preferredLogicalFacilityIds: [ID!] birthdayWithinDays: Int purchase: SegmentPurchaseAxisInput "The tag axis (at most 16, unique) — each ref in-tenant + active at write." tagIds: [ID!] } "The tenant stamps server-side; dynamic REQUIRES a predicate (static refuses predicate/excludedConsumerIds — the cross-type field law)." input NewSegmentInput { "Optional: when omitted the per-type default applies — the type word (e.g. `static segment`); when supplied it must be non-blank." caption: String "static | dynamic — IMMUTABLE at birth." segmentType: SegmentType! "REQUIRED on dynamic, refused on static." predicate: SegmentPredicateInput "Dynamic-only manual exclusions (≤256 unique in-tenant consumers)." excludedConsumerIds: [ID!] } "Edit-input for a Segment. Every field optional, at least ONE required; supplied fields REPLACE segmentType is IMMUTABLE at birth. On dynamic: predicate replaces WHOLESALE (never clearable) and excludedConsumerIds replaces wholesale (releases) — the membership re-materializes at the next refreshSegment; both refuse on static (the cross-type law). Static membership moves via addSegmentMembers/removeSegmentMembers." input EditSegmentInput { caption: String "Wholesale replacement (dynamic-only)." predicate: SegmentPredicateInput "Wholesale replacement (dynamic-only; releases)." excludedConsumerIds: [ID!] } "The v1 canned metric roster." enum DashboardMetric { sales_today sales_week orders_open sell_through_30d inventory_value low_stock_count cs_open_cases review_average loyalty_signups_30d fraud_alerts_open } "One widget row — a canned metric at a unique layout ordinal." type DashboardWidget { metricKey: DashboardMetric! ordinal: Int! } "A Dashboard: a merchant-authored CANNED-METRIC widget layout (no ad-hoc OLAP: the construct stores the LAYOUT only; every output derives downstream of the event lake; the office renderer realizes the tokens when the face lands). widgets = 1..16 ordered rows, each naming ONE canned metric (the v1 roster: sales_today · sales_week · orders_open · sell_through_30d · inventory_value · low_stock_count · cs_open_cases · review_average · loyalty_signups_30d · fraud_alerts_open); ordinals unique; wholesale-replace on edit. NOT searchable." type Dashboard { id: ID! "The group-scoped human-facing system id (DA-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Dashboard parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The ordered canned-metric layout — wholesale-replace on edit (the CouponEffect class); ordinals unique." widgets: [DashboardWidget!]! } "One page of the dashboards listing — the records + the opaque resume cursor." type DashboardPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Dashboard!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One widget row input — metricKey ∈ the canned roster; ordinals unique within the dashboard." input DashboardWidgetInput { metricKey: DashboardMetric! ordinal: Int! } "The tenant stamps server-side; widgets 1..16, ordinals unique, every metricKey ∈ the canned roster." input NewDashboardInput { "Optional: when omitted the per-type default applies — the widget count (e.g. `dashboard ×4`); when supplied it must be non-blank." caption: String "The initial layout (1..16; ordinals unique)." widgets: [DashboardWidgetInput!]! } "Edit-input for a Dashboard. Every field optional, at least ONE required; supplied fields REPLACE widgets replace WHOLESALE when supplied (the CouponEffect class — never merged); caption and/or widgets, at least one." input EditDashboardInput { caption: String "Wholesale replacement when supplied." widgets: [DashboardWidgetInput!] } "A Report (📊; THE REPORT ENGINE, program 3 of THE OFFICE FIX PROGRAM 2): a SAVED REPORT DEFINITION — a validated ReportSpec (the reportRun grammar VERBATIM: a plan + columns, or a plan + groupBy/measures, an optional sort) kept as JSON text (specJson, at most 12288 characters) with its words (describeReport, at most 4096 characters) and the family its rows or groups are made of (terminalFamily). It stores NO result: every run executes as THE RUNNER under the runner's own list rights through reportRun(reportId) (rows on screen, now) or startExportJob(reportId, format) (a file, in the background); the saved spec is RE-VALIDATED at every run (a roster that moved since the save refuses in the teaching voice — edit the spec); only an active definition runs. The definition is the question, never an answer. NOT searchable (no filter roster until the report builder lands)." type Report { id: ID! "The group-scoped human-facing system id (RO-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Report parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The validated ReportSpec as JSON text (the planJson idiom — the receiver parses; at most 12288 characters); replaced WHOLESALE by updateReport(spec) and re-validated at every run." specJson: String! "The spec in words (describeReport; at most 4096 characters — cut with a trailing … past it) — derived at write; what the list shows before anything runs." words: String! "The family the rows or groups are made of (the plan’s last hop’s family, or the start’s) — derived at write, never caller-supplied." terminalFamily: String! "What the report is for — a sentence or three (at most 512 characters); optional, set-only." description: String } "One page of the reports listing — the records + the opaque resume cursor." type ReportPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Report!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The tenant stamps server-side; the spec validates through THE REPORT GATE (validateReport — THE PLAN GATE, then the columns / groupBy / measures / sort arms against the terminal family’s roster); words + terminalFamily derive from it (ReportSpecInput is the reportRun input — nothing new on the wire)." input NewReportInput { "Optional: when omitted the per-type default applies — the terminal family (e.g. `Order report`); when supplied it must be non-blank." caption: String "The definition — the reportRun grammar VERBATIM (a plan + columns, or a plan + groupBy/measures, an optional sort); validated now, run later as whoever runs it." spec: ReportSpecInput! "What the report is for (at most 512 characters)." description: String } "Edit-input for a Report. Every field optional, at least ONE required; supplied fields REPLACE spec replaces WHOLESALE when supplied (never merged) and re-derives words + terminalFamily; caption, description and/or spec — at least one." input EditReportInput { caption: String "What the report is for (at most 512 characters); set-only." description: String "Wholesale replacement when supplied — validated by THE REPORT GATE; words + terminalFamily re-derive." spec: ReportSpecInput } "A Collaborator — the strictly-scoped NON-ACCOUNT access identity: the User-adjacent NEVER-OWNER identity for EXTERNALLY-ORIGINATED parties (outside accountant/bookkeeper, agency, consultant, an integration partner's human operator, a scoped helper) granted limited access to ONE org group without being a merchant Account. Group-scoped like the Consumer (parentId === rootId — per-group NOT global; the same firm at two merchant groups = two records; federated identity is the lock's flagged-not-now). THE THREE DISTINCTIONS FROM A USER: (1) no merchant Account (its own identity + credential + session class) · (2) NO OWNERSHIP EVER (owners are Account-only structural links — there is no Collaborator state in which ownership is permitted) · (3) externally-originated (invited, not part of the merchant's principal hierarchy). Access = STRICTLY the Roles-per-org mechanism Users ride. the identity-marker rule (the Consumer burn class): the (group × normalized email) UNIQ marker IS the login index — a live/inactive holder refuses CONFLICT/IDENTITY_TAKEN; on erase (doom) the identifiers BURN within the group. Credentials NEVER ride this record: a created Collaborator is born active but CREDENTIAL-LESS — issueCollaboratorInvite mints the show-once bootstrap token, acceptCollaboratorInvite redeems it into the argon2id credential (the invite handshake is a credential-store bootstrap, NOT an FSM state — the lock's chosen lean; NO staff password-set lane EVER — recovery = re-invite rotation). Self-service rides the COLLABORATOR SESSION channel (collaboratorLogin + descriptor-gated ops); staff manage via THIS face. SEARCHABLE (the book law)." type Collaborator { id: ID! "The group-scoped human-facing system id (CX-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a Collaborator parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The login identity — stored NORMALIZED (trim + lowercase, the class); the (group × email) UNIQ marker rides it." email: String! "The external party's display name; absent ⇒ the caption carries the identity line (the normalized email). NO further profile block — data minimization." displayName: String "No further notes." orgRoles: [UserOrgRoles!]! } "One page of the collaborators listing — the records + the opaque resume cursor." type CollaboratorPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Collaborator!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "Create-input for a Collaborator. The tenant (org group) is derived SERVER-SIDE from the principal. ⚠ NO password and NO invite token here — a created Collaborator is CREDENTIAL-LESS (it cannot log in) until issueCollaboratorInvite mints the show-once bootstrap token and the external party accepts it. orgRoles is required but MAY be empty; refs validated STRICT (in-tenant + active — the gate VERBATIM)." input NewCollaboratorInput { "Optional: when omitted the per-type default applies — the display name when given, else the NORMALIZED email (the identity line); when supplied it must be non-blank." caption: String "The login identity — normalized server-side; the (group × email) UNIQ marker reserves in the create transaction." email: String! displayName: String "The initial role-assignment set; may be empty (no org access yet)." orgRoles: [UserOrgRolesInput!]! } "Edit-input for a Collaborator. Every field optional, at least ONE required; supplied fields REPLACE. orgRoles REPLACES WHOLESALE when supplied (the EditUser list-is-the-payload semantic; supplying strips every assignment — live sessions keep their self plane but every descriptor-gated op refuses at the next call); every referenced org + role must be in-tenant AND active (CONFLICT/REF_STATE). An email edit is the identity-marker release/reserve swap under the burn law (a live/inactive/DOOMED holder of the NEW value refuses CONFLICT/IDENTITY_TAKEN; the OLD value releases)." input EditCollaboratorInput { caption: String "The replacement login identity — normalizes server-side; the marker swap gates it (the burn law)." email: String displayName: String "The FULL desired assignment set (wholesale replacement — strips every assignment)." orgRoles: [UserOrgRolesInput!] } "A bookable-resource kind." enum SchedulableResourceType { staff station equipment } "A weekday name (working-hours rows — self-documenting names, never magic ints)." enum Weekday { mon tue wed thu fri sat sun } "One weekly working-hours window — NAIVE WALL-CLOCK minutes at the facility (the estate carries no timezone; ADVISORY v1 — no gate consumes it). closeMinute is exclusive (1440 = midnight-end); multiple windows per weekday = split shifts." type WorkingHoursWindow { weekday: Weekday! "Opening minute-of-day (0..1439)." openMinute: Int! "Closing minute-of-day, exclusive (1..1440); must exceed openMinute." closeMinute: Int! } "A SchedulableResource — a bookable entity at a LogicalFacility: the staff member / station / equipment Appointments book against. capacity = concurrent bookings (default 1); the confirm gate checks CAPACITY ONLY. workingHours are ADVISORY v1 — naive wall-clock weekly windows (the estate carries no timezone — the map disclosed boundary): the availability read returns them, NO gate consumes them. The OPERATIONAL lifecycle verbatim. The gate: a RESERVED booking (a confirmed/in_progress Appointment) blocks deactivate AND doom, CONFLICT/REFERENCED naming the appointments; requested Appointments deliberately do NOT block (they refuse honestly at confirm via the ACTIVE re-read)." type SchedulableResource { id: ID! "The group-scoped human-facing system id (SR-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent LogicalFacility; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned resource kind — set at creation, IMMUTABLE (re-kind = create + doom)." resourceType: SchedulableResourceType! "The optional staff link — staff-kind resources only; in-tenant + ACTIVE at set; editable (re-staffing is operational reality); null = no link." userId: ID "Concurrent-booking capacity (1..100; default 1) — the confirm gate refuses CONFLICT/DOUBLE_BOOKED at this ceiling unless the appointment.overbook_allowed policy admits." capacity: Int! "The weekly working-hours calendar (≤28 windows; split shifts legal; empty = none declared) — ADVISORY v1: naive wall-clock minutes at the facility, returned by the availability read, consumed by NO gate." workingHours: [WorkingHoursWindow!]! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the schedulableResources listing — the records + the opaque resume cursor." type SchedulableResourcePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [SchedulableResource!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "One weekly working-hours window — openMinute < closeMinute (VALIDATION/INVALID otherwise); at most 28 windows per resource." input WorkingHoursWindowInput { weekday: Weekday! openMinute: Int! closeMinute: Int! } "Create-input for a SchedulableResource. The tenant (org group) is derived SERVER-SIDE from the principal; logicalFacilityId (the parent — rides the header) is tenant-scoped server-side and must be ACTIVE (any LF classification — does not restrict booking sites). userId is legal on staff resources ONLY (in-tenant + ACTIVE — CONFLICT/REF_STATE else); capacity defaults to 1; workingHours defaults to." input NewSchedulableResourceInput { "Optional: when omitted the per-type default applies — the kind + LF coordinate ('staff at '); when supplied it must be non-blank." caption: String "The parent LogicalFacility (the booking site) — tenant-scoped + ACTIVE. Immutable after birth." logicalFacilityId: ID! "The canned kind — IMMUTABLE at birth." resourceType: SchedulableResourceType! "The optional staff link — staff-kind only (refused otherwise); in-tenant + ACTIVE." userId: ID "Concurrent-booking capacity (1..100); omitted = 1." capacity: Int "The weekly advisory calendar; omitted =." workingHours: [WorkingHoursWindowInput!] code: String } "Edit-input for a SchedulableResource. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic) EXCEPT userId, where null explicitly CLEARS the staff link (the EditPlugin.apiKeyId nullish-clear law). The parent LF and resourceType are IMMUTABLE at birth (re-home/re-kind = create + doom). A supplied workingHours array REPLACES wholesale." input EditSchedulableResourceInput { caption: String "Set (staff-kind only — CONFLICT/REF_STATE else) or null-CLEAR the staff link." userId: ID "1..100 — raising/lowering re-gates NOTHING retroactively (existing reservations stand; the ceiling applies at future confirms)." capacity: Int "The wholesale replacement (strips every window)." workingHours: [WorkingHoursWindowInput!] code: String } "A booking purpose: a service-type product sale, or an order pickup." enum AppointmentPurpose { service pickup } "An Appointment — a booking of 1..8 SchedulableResources at an LF for a time window: a service-type product sale (purpose service — variantId REQUIRED, the styleType walk gates it) OR an order pickup (purpose pickup — orderId REQUIRED, the order being collected). The ratified lifecycle VERBATIM: confirm reserves capacity (the RESBOOK calendar rows; the gate is CAPACITY-ONLY — CONFLICT/DOUBLE_BOOKED unless the appointment.overbook_allowed policy admits); no_show fires from the scheduler ONLY (noShowAt = startAt + the appointment.no_show_window_minutes policy, stamped at confirm — NO caller op); rescheduled = a DOOMED terminal superseded by the linked successor (born requested — ITS confirm re-runs the capacity gate); completed may LINK an order for billing (the complete-time orderId — auto-minting a line is a named growth). durationMinutes ≤ 1440 (24h — the overlap-lookback bound). The create-time gates: appointment.lead_time_minutes + appointment.max_advance_days." type Appointment { id: ID! "The group-scoped human-facing system id (AP-…)." sysId: String! type: String! caption: String! "The FSM state: requested | confirmed | in_progress | completed | no_show | cancelled | rescheduled." status: String! "The parent LogicalFacility; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The LF’s Organization — SERVER-stamped at create (the weld; the policy chain’s key)." organizationId: ID! "The booking purpose (service | pickup) — IMMUTABLE at birth (re-purpose = cancel + rebook)." purpose: AppointmentPurpose! "The service-type product variant sold: REQUIRED on service, FORBIDDEN on pickup." variantId: ID "The linked Order: REQUIRED on pickup (the order being collected); optional on service (sold-together at create/update, or book-then-bill at complete)." orderId: ID "The booked SchedulableResources (1..8, distinct; each in-tenant + ACTIVE + at the SAME LF as the parent)." resourceIds: [ID!]! "The window start — a UTC ISO-8601 instant (the estate carries no timezone; working hours are advisory)." startAt: String! "The window length in minutes (1..1440 — the 24h cap IS the overlap-query lookback bound)." durationMinutes: Int! "The polymorphic customer capture (the Order block VERBATIM — inline fields + the corporateCustomerId/consumerId ref arms); optional (a pickup’s customer is the order’s)." customer: OrderCustomer "SYSTEM-stamped at confirm = startAt + the resolved appointment.no_show_window_minutes — the scheduler marks no_show at this instant if the appointment is still confirmed." noShowAt: String "SYSTEM-stamped by reschedule on the superseded terminal — the linked successor (the ratified pair)." successorAppointmentId: ID "SYSTEM-stamped on a reschedule-born successor — the appointment it supersedes." predecessorAppointmentId: ID } "One page of the appointments listing — the records + the opaque resume cursor." type AppointmentPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Appointment!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for an Appointment. The tenant is derived SERVER-SIDE; logicalFacilityId is tenant-scoped + ACTIVE; every resourceId in-tenant + ACTIVE + at the SAME LF; the purpose arms: service ⇒ variantId REQUIRED (the service-type walk), pickup ⇒ orderId REQUIRED + variantId FORBIDDEN; a named orderId must be a non-doomed-class in-tenant Order; the customer ref arms gate like the Order block. The create gates: startAt ≥ now + appointment.lead_time_minutes AND ≤ now + appointment.max_advance_days (VALIDATION/INVALID naming the key)." input NewAppointmentInput { "Optional: when omitted the per-type default applies — the purpose + LF coordinate ('service appointment at '); when supplied it must be non-blank." caption: String "The parent LogicalFacility (the booking site) — tenant-scoped + ACTIVE. Immutable after birth." logicalFacilityId: ID! "IMMUTABLE at birth." purpose: AppointmentPurpose! "REQUIRED on service (a service-type variant); FORBIDDEN on pickup." variantId: ID "REQUIRED on pickup; optional on service (the sold-together pattern)." orderId: ID "The resources to book (1..8, distinct)." resourceIds: [ID!]! "The UTC start instant." startAt: String! "1..1440." durationMinutes: Int! "Optional — the Order customer-capture grammar verbatim." customer: OrderCustomerInput } "Edit-input for a Appointment. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved (no clearing semantic). THE STATE LADDER: requested accepts every field; confirmed/in_progress accept ONLY caption/customer/orderId — window or resource moves on a confirmed booking are a RESCHEDULE (the capacity-gate-dodge designed out); terminals refuse CONFLICT/IMMUTABLE. The parent LF and purpose are IMMUTABLE at birth." input EditAppointmentInput { caption: String "requested-only; service purpose only — the walk re-gates." variantId: ID "The link (any live state; a doomed-class order refuses REF_STATE)." orderId: ID "requested-only; wholesale replacement — in-tenant + ACTIVE + same-LF re-gated." resourceIds: [ID!] "requested-only; the lead/advance gates re-run." startAt: String "requested-only." durationMinutes: Int "REPLACES the block when supplied." customer: OrderCustomerInput } "A Storefront — the ecom DTC PUBLISH-CONFIG document: which selling facility the site sells from, which canned theme renders it, which collections it merchandises, which browse tree and channel division frame it, and (optionally) the custom domain it claims. The lifecycle: born draft (claiming nothing) → publish (THE INVALID_CONFIG GATE re-validates every ref record-aware + the GLOBAL domain marker claims in the SAME transaction — CONFLICT/IDENTITY_TAKEN if another published site holds the name) → unpublish (the marker releases) → republish (the SAME gate + re-claim). published NEVER dooms — unpublish first (the FSM forbids the edge). THE SERVING ESTATE IS DELIBERATELY ABSENT v1 (the map): publish flips state, claims the domain, validates config — it provisions NOTHING; this record is the control plane the DTC workstream will consume. SEO copy rides the Decoration attachment, never fields here." type Storefront { id: ID! "The group-scoped human-facing system id (SF-…)." sysId: String! type: String! caption: String! "The FSM state: draft | published | unpublished | doomed." status: String! "The parent Organization; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The DESIGNATED SELLING facility — the LF whose stock/pricing context the site sells from; in-tenant + ACTIVE at set AND at publish; edit-locked while published (unpublish → edit → republish)." logicalFacilityId: ID! "The canned theme key (cannedStorefrontThemes lists the roster: almond-light · almond-dark · gallery · catalog-classic) — merchants pick, never author; edit-locked while published." theme: String! "The claimed custom domain (a bare lowercase hostname, at most 253 characters — no scheme/path/port/IP/localhost): the GLOBAL uniqueness marker holds it ONLY while published (claim at publish, release at unpublish); edit-locked while published; null = no custom domain (the default host is the serving workstream's business)." customDomain: String "The merchandised Collections (0..24, distinct; each in-tenant + ACTIVE) — edits replace the set WHOLESALE; a NON-doomed storefront blocks a referenced collection's doom." collectionIds: [ID!]! "No further notes." categoryId: ID "The CHANNEL-type Division framing this site (optional — the channel slot’s FIRST consumer; in-tenant + ACTIVE + divisionType channel); null = unframed." divisionId: ID } "One page of the storefronts listing — the records + the opaque resume cursor." type StorefrontPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [Storefront!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Create-input for a Storefront. The tenant (org group) derives SERVER-SIDE from the principal; organizationId (the parent) is tenant-scoped server-side and must be ACTIVE; the config refs (selling LF / theme roster / collections / channel division / root category) gate record-aware at create AND re-validate at every publish." input NewStorefrontInput { "Optional: when omitted the per-type default applies — the domain when given ('storefront at '), else the theme (' storefront'); when supplied it must be non-blank." caption: String "The parent Organization (whose storefront this is) — tenant-scoped + ACTIVE. Immutable after birth." organizationId: ID! "The designated selling LF — tenant-scoped + ACTIVE." logicalFacilityId: ID! "A canned theme key — cannedStorefrontThemes lists the roster (an unknown key refuses NAMING it)." theme: String! "The optional custom domain (the bare-hostname grammar) — validated for SHAPE here; the claim happens at publish." customDomain: String "The merchandised collections (0..24, distinct, each ACTIVE); omitted =." collectionIds: [ID!] "The optional browse-tree root category (ACTIVE)." categoryId: ID "The optional CHANNEL-type division (ACTIVE + channel-kind — a different kind refuses)." divisionId: ID } "Edit-input for a Storefront. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved — customDomain/categoryId/divisionId take null to CLEAR (the EditPlugin.apiKeyId nullish-clear law); a supplied collectionIds REPLACES wholesale. THE PUBLISHED EDIT-LOCK: while published, theme / logicalFacilityId / customDomain refuse naming the fields (unpublish → edit → republish — the domain marker never dangles); caption/collections/category/division edit freely on a live site (merchandising is normal lifecycle). The parent Organization is IMMUTABLE at birth." input EditStorefrontInput { caption: String "Re-home the selling facility (ACTIVE; refused while published)." logicalFacilityId: ID "Re-theme (a canned key; refused while published)." theme: String "Set (the bare-hostname grammar) or null-CLEAR the domain (refused while published)." customDomain: String "The wholesale replacement (strips every collection); each ACTIVE." collectionIds: [ID!] "Set (ACTIVE) or null-CLEAR the browse-tree anchor." categoryId: ID "Set (ACTIVE + channel-kind) or null-CLEAR the channel framing." divisionId: ID } "A fulfillment method an agent channel offers." enum AgentChannelFulfillmentMethod { ship pickup_instore pickup_curbside } "The canned request-rate class an agent channel grants its platforms." enum AgentChannelRateClass { low normal high } "ONE flat-rate shipping card — the platform shows the caption and charges amountMinor (the checkout’s fulfillment total) to the named countries, quoting minDays..maxDays transit; the id is the stable slug the platform echoes when the buyer picks it." type AgentChannelShippingOption { "A lowercase slug (letters, digits, interior hyphens; at most 32 characters), unique within the channel." id: String! caption: String! "ISO 3166-1 alpha-2 codes (uppercase), each a channel ship-to country." countries: [String!]! "The flat rate in the organization’s currency minor units (0 = free shipping)." amountMinor: Int! "Transit window in days (0..365; minDays ≤ maxDays)." minDays: Int! maxDays: Int! } "ONE pre-approved agent platform: profileUrl is the platform’s OWN UCP profile (its signing keys are read from it); webhookUrl OVERRIDES the URL the platform advertises in its own profile (the order capability’s config.webhook_url) — absent = the profile’s; the deliverer POSTs the signed full order document there; active false keeps the row but refuses the platform." type AgentChannelPlatform { "An https URL (the egress law — no credentials, no port, no IP-literal or private hosts; at most 512 characters)." profileUrl: String! caption: String! webhookUrl: String active: Boolean! } "The UCP buyer_consent defaults an agent channel proposes — every purpose a boolean." type AgentChannelConsentDefaults { marketing: Boolean! analytics: Boolean! preferences: Boolean! sale_or_sharing: Boolean! } "The PUBLIC half of an ES256 signing key as a JWK (RFC 7517/7518 — kty EC · crv P-256 · the x/y coordinates in base64url)." type AgentChannelPublicJwk { kty: String! crv: String! x: String! y: String! } "ONE engine-minted signing key on an agent channel: kid = the RFC 7638 thumbprint of the public JWK; retiresAt is set on the OUTGOING key by a rotation (now + the grace) — a key past it is pruned at the next rotation and never published." type AgentChannelSigningKey { kid: String! publicJwk: AgentChannelPublicJwk! createdAt: String! retiresAt: String } "An AgentChannel — the merchant’s CONTROLS over the agentic-commerce channel: exactly ONE record per Organization that says WHAT an AI shopping agent may sell over the open Universal Commerce Protocol and HOW — the selling location (prices · stock · tax origin), the listed Collections (EMPTY = nothing listed), an optional agent price plane (a PriceList), discount codes on/off, a checkout cap, the fulfillment methods + flat-rate shipping cards + ship-to countries + pickup locations, the buyer facts required, the pre-approved agent platforms (EMPTY = every platform refused), the buyer-consent defaults, the return/warranty policy texts, the checkout session TTL, and the engine-minted ES256 signing keys (the PUBLIC halves — the private halves live in the credential store, never on the wire). Lifecycle draft → live → paused → live | doomed: publish and resume run the completeness rule record-aware (the channel must be able to sell); pause withholds the channel (agents read unavailable + Retry-After); a LIVE channel never dooms in one step (pause first); doom releases the one-per-org marker so the organization may start over. The protocol doors (the profile, the catalog, the checkout — onward) READ this record; the adapter adds no business rule of its own. Payment handlers are NEVER typed here — the profile derives them from the organization’s connected-account facts." type AgentChannel { id: ID! "The group-scoped human-facing system id (AG-…)." sysId: String! type: String! caption: String! "The FSM state: draft | live | paused | doomed." status: String! "The parent Organization; rootId = the org group; parentId!== rootId always." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "WHERE — the selling location: the LogicalFacility whose stock, prices and tax origin the channel sells from; in-tenant + ACTIVE at every write and at publish/resume." logicalFacilityId: ID! "WHERE — the business locations offered for pickup (0..16, distinct, each in-tenant + ACTIVE); REQUIRED non-empty when a pickup method is offered; edits replace the set WHOLESALE." pickupLogicalFacilityIds: [ID!]! "WHERE — the ISO 3166-1 alpha-2 countries (UPPERCASE) the channel ships to (0..64, distinct); EMPTY = no shipping (an address outside answers address_undeliverable); REQUIRED non-empty when ship is offered; replaces WHOLESALE." shipToCountries: [String!]! "WHAT — the listed Collections: the ONLY listing lever — EMPTY = nothing is listed (publish refuses); replaces WHOLESALE. A non-doomed channel blocks a listed collection’s doom." collectionIds: [ID!]! "WHAT — an optional CHANNEL-type Division framing the agent channel; null = unframed." divisionId: ID "WHAT — whether agents read stock FIGURES (true) or only in/out of stock (false — the strict default)." showStockLevels: Boolean! "WHAT — the hand veto list: Variants never listed whatever their Collections say (0..200, distinct, each in-tenant); replaces WHOLESALE." excludedVariantIds: [ID!]! "PRICES — an optional PriceList as the agent price plane (in-tenant + ACTIVE + selected for the owning organization + unscoped — a customer-scoped contract list refuses); null = the standing sale prices apply. Explicit prices, never blanket percentages." priceListId: ID "PRICES — whether agents may present discount codes (the UCP discount extension is advertised only when true; the engine’s own coupon gates still apply). Strict default false." allowDiscountCodes: Boolean! "PRICES — an optional cap on a single agent checkout in the organization’s currency minor units (1..2147483647); a checkout over it answers eligibility_invalid; null = no cap." maxCheckoutTotalMinor: Int "FULFILLMENT — the offered methods (ship · pickup_instore · pickup_curbside; distinct); EMPTY = the channel cannot complete a checkout (publish refuses)." fulfillmentMethods: [AgentChannelFulfillmentMethod!]! "FULFILLMENT — the flat-rate shipping cards (0..16, ids unique): the merchant’s own words and prices; every card’s countries must be ship-to countries; REQUIRED non-empty when ship is offered; replaces WHOLESALE." shippingOptions: [AgentChannelShippingOption!]! "FULFILLMENT — handling days before a shipment leaves (0..30; default 0)." handlingDays: Int! "PAYMENTS — the buyer must give an email before completing (strict default true)." requireBuyerEmail: Boolean! "PAYMENTS — the buyer must give a phone number before completing (default false)." requireBuyerPhone: Boolean! "PLATFORMS — the pre-approved agent platform registry (0..16, profile URLs unique): a platform is verified against ITS profile’s signing keys and refused (profile_not_trusted) unless listed and active — EMPTY = every platform refused; publish requires at least one active; replaces WHOLESALE." allowedPlatforms: [AgentChannelPlatform!]! "PLATFORMS — the canned request-rate class granted to platforms (low · normal · high; default normal)." rateClass: AgentChannelRateClass! "CONSENT — the UCP buyer_consent defaults the channel proposes (marketing · analytics · preferences · sale_or_sharing); strict default all false." consentDefaults: AgentChannelConsentDefaults! "POLICIES — the return policy text (at most 2000 characters), published in the profile’s policies; null = none published." returnPolicy: String "POLICIES — the warranty policy text (at most 2000 characters), published in the profile’s policies; null = none published." warrantyPolicy: String "SESSION — how long an agent checkout stays open (15..1440 minutes; default 360 — the spec’s 6 h); the draft order’s validUntil derives from it." checkoutTtlMinutes: Int! "SESSION — whether buyer account linking (the UCP identity_linking capability) is advertised: the shop host serves its own OAuth 2.0 endpoints and buyers sign in on the shop’s address to link an assistant; default false." identityLinking: Boolean! "SESSION: whether every checkout and order operation requires a LINKED buyer (the standard’s members-only posture — an unlinked call answers 401 identity_required); default false = guest checkout stands." requireLinkedBuyer: Boolean! "ENGINE-STAMPED — the public ES256 signing keys (1..4: the current key + the outgoing keys inside their 7-day grace), published as the profile’s keys; minted at birth, grown by rotateAgentChannelKey, never caller-typed. The private halves live in the credential store." signingKeys: [AgentChannelSigningKey!]! } "One page of the agentChannels listing — the records + the opaque resume cursor." type AgentChannelPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [AgentChannel!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "A flat-rate shipping card for an agent channel — the same shape the record carries." input AgentChannelShippingOptionInput { id: String! caption: String! countries: [String!]! amountMinor: Int! minDays: Int! maxDays: Int! } "A pre-approved agent platform for an agent channel — the same shape the record carries." input AgentChannelPlatformInput { profileUrl: String! caption: String! webhookUrl: String active: Boolean! } "The buyer_consent defaults for an agent channel — every purpose required." input AgentChannelConsentDefaultsInput { marketing: Boolean! analytics: Boolean! preferences: Boolean! sale_or_sharing: Boolean! } "Create-input for an AgentChannel. The tenant (org group) derives SERVER-SIDE from the principal; organizationId (the parent) is tenant-scoped server-side and must be ACTIVE; the referenced records gate record-aware IN THE KIT. Every control is optional — an omitted control takes its strict default (nothing listed · no shipping · no pickup · no platforms · stock hidden · codes off · consent all false · email required · normal rate · 6 h)." input NewAgentChannelInput { "Optional: when omitted the per-type default applies — the owning organization’s name + ' agent channel'; when supplied it must be non-blank." caption: String "The parent Organization (whose channel this is) — tenant-scoped + ACTIVE; exactly one channel per org. Immutable after birth." organizationId: ID! "The selling location — tenant-scoped + ACTIVE." logicalFacilityId: ID! "Pickup locations (0..16, distinct, each ACTIVE); omitted =." pickupLogicalFacilityIds: [ID!] "Ship-to countries (ISO alpha-2 uppercase; 0..64, distinct); omitted = (no shipping)." shipToCountries: [String!] "The listed collections (0..24, distinct, each ACTIVE); omitted = (nothing listed)." collectionIds: [ID!] "The optional CHANNEL-type division (ACTIVE + channel-kind — a different kind refuses)." divisionId: ID "Show stock figures to agents; omitted = false." showStockLevels: Boolean "Variants never listed (0..200, distinct, in-tenant); omitted =." excludedVariantIds: [ID!] "The optional agent price list (ACTIVE; selected for the owning organization; unscoped)." priceListId: ID "Accept discount codes from agents; omitted = false." allowDiscountCodes: Boolean "The optional single-checkout cap in minor units (≥ 1)." maxCheckoutTotalMinor: Int "The offered methods (distinct); omitted = (publish then refuses until set)." fulfillmentMethods: [AgentChannelFulfillmentMethod!] "The flat-rate shipping cards (0..16, ids unique); omitted =." shippingOptions: [AgentChannelShippingOptionInput!] "Handling days (0..30); omitted = 0." handlingDays: Int "Require the buyer’s email; omitted = true." requireBuyerEmail: Boolean "Require the buyer’s phone; omitted = false." requireBuyerPhone: Boolean "The pre-approved platforms (0..16, profile URLs unique, https); omitted = (every platform refused)." allowedPlatforms: [AgentChannelPlatformInput!] "The request-rate class; omitted = normal." rateClass: AgentChannelRateClass "The buyer_consent defaults; omitted = all false." consentDefaults: AgentChannelConsentDefaultsInput "The return policy text (at most 2000 characters)." returnPolicy: String "The warranty policy text (at most 2000 characters)." warrantyPolicy: String "The checkout window (15..1440 minutes); omitted = 360." checkoutTtlMinutes: Int "Advertise buyer account linking; omitted = false." identityLinking: Boolean "Require a signed-in (linked) buyer for every checkout and order operation; omitted = false." requireLinkedBuyer: Boolean } "Edit-input for a AgentChannel. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved — divisionId / priceListId / maxCheckoutTotalMinor / returnPolicy / warrantyPolicy take null to CLEAR (the EditPlugin.apiKeyId nullish-clear law); a supplied list REPLACES wholesale. Edits land in every live state and take effect on the next agent request; the live-stays-complete rule: an edit on a LIVE channel that would leave it unable to sell (nothing listed · no method · shipping without countries or cards · pickup without a location · no active platform) refuses VALIDATION/INVALID naming the gap — pause first to reshape it. status and signingKeys never ride an edit." input EditAgentChannelInput { caption: String "Re-home the selling location (ACTIVE)." logicalFacilityId: ID "The wholesale replacement (strips every pickup location); each ACTIVE." pickupLogicalFacilityIds: [ID!] "The wholesale replacement (= no shipping)." shipToCountries: [String!] "The wholesale replacement (= nothing listed); each ACTIVE." collectionIds: [ID!] "Set (ACTIVE + channel-kind) or null-CLEAR the channel framing." divisionId: ID showStockLevels: Boolean "The wholesale replacement of the veto list." excludedVariantIds: [ID!] "Set (ACTIVE; selected for the owning organization; unscoped) or null-CLEAR the agent price plane." priceListId: ID allowDiscountCodes: Boolean "Set (≥ 1) or null-CLEAR the checkout cap." maxCheckoutTotalMinor: Int "The wholesale replacement (distinct)." fulfillmentMethods: [AgentChannelFulfillmentMethod!] "The wholesale replacement (ids unique)." shippingOptions: [AgentChannelShippingOptionInput!] handlingDays: Int requireBuyerEmail: Boolean requireBuyerPhone: Boolean "The wholesale replacement (profile URLs unique, https)." allowedPlatforms: [AgentChannelPlatformInput!] rateClass: AgentChannelRateClass consentDefaults: AgentChannelConsentDefaultsInput "Set or null-CLEAR the return policy text." returnPolicy: String "Set or null-CLEAR the warranty policy text." warrantyPolicy: String checkoutTtlMinutes: Int identityLinking: Boolean requireLinkedBuyer: Boolean } "the budget rule: at most 50000 records examined (the estimate refuses a plan that cannot fit, with the numbers) · 300 s from the start (past it the job is expired WITH its partials) · 400 machine steps. ONE running job per signed-in session (the SEARCHLOCK marker — a second start refuses CONFLICT/SEARCH_JOB_ACTIVE naming the holder). Lifecycle queued → running → done | cancelled | expired | failed: cancel is the owner's (cancelSearchJob) or the session's end; done stays listed, the other terminals are doomed-class. The generic wire is READ-ONLY (the two reads) — the bespokes own the writes: startSearchJob (THE PLAN GATE, then the per-family list-op offer AS THE CALLER — a family you may not list stops the plan before any read) · cancelSearchJob · searchJobMatches (gated by the READER's own list right over the plan's terminal family)." type SearchJob { id: ID! "The group-scoped human-facing system id (SJ-…)." sysId: String! type: String! caption: String! "The FSM state: queued | running | done | cancelled | expired | failed." status: String! "The parent org group (the Saga shape); for a SearchJob parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The owner — the User who started the job; cancel is theirs (the system hook cancels on their session’s end). IMMUTABLE at birth." userId: ID! "The signed-in session the job runs under — the SEARCHLOCK aggregate (ONE running job per session); a Session is not a catalog construct, so the id is opaque on the wire. IMMUTABLE at birth." sessionId: ID! "The NORMALIZED plan as JSON text (the validated SearchPlan with its defaults applied; at most 8192 characters) — re-parsed and re-validated at every read. IMMUTABLE at birth." planJson: String! "IMMUTABLE at birth." words: String! "Machine steps taken so far (0 at birth; stamped by the step lane)." stepsDone: Int! "Records examined so far across every walk and hydrate (0 at birth) — the budget law’s counter." examined: Int! "The terminal step’s WHOLE match count (0 until the finish; the result row carries at most the plan’s limit of summaries)." matchCount: Int! "The running instant (UTC ISO-8601 — the clock’s zero). Null while queued." startedAt: String "The terminal instant (UTC ISO-8601). Null while live." finishedAt: String "Why the run stopped short — the executor’s refusal in its teaching voice (the budget, the frontier, the step cap), the expiry, the start refusal, or a machine fault’s cause. Null on done." problem: String "The ops/reconcile handle." sfExecutionArn: String "The result row’s ttl (epoch SECONDS = finishedAt + 7 days) — the expiry the matches read derives its expiresAt from. Null until the finish." resultTtl: Int } "One page of the searchJobs listing — the records + the opaque resume cursor." type SearchJobPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [SearchJob!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The record is the durable truth (stepsDone · examined · partCount · rowCount · bytes grow; partial says the run stopped short; problem says why). the budget rule is the SearchJob's VERBATIM — at most 50000 records examined · 300 s from the start (past it the job is expired WITH the parts written) · 400 machine steps — plus ONE bound of its own: 256 MiB on the composed file (the walk halts partial the step before it would cross). The plan's limit does NOT bound the export — every terminal record is written. ONE running export per signed-in session (the EXPORTLOCK marker — a second start refuses CONFLICT/EXPORT_JOB_ACTIVE naming the holder; a running search does not block it). Lifecycle queued → running → done | cancelled | expired | failed: cancel is the owner's (cancelExportJob) or the session's end — NO file is composed on cancel; done stays listed, the other terminals are doomed-class. The generic wire is READ-ONLY (the two reads) — the bespokes own the writes: startExportJob (THE PLAN GATE, then the per-family list-op offer AS THE CALLER — a family you may not list stops the plan before any read; the format csv | jsonl) · cancelExportJob · exportJobDownload (a query — the owner alone AND the reader's own list right over the plan's terminal family). The finish mints an in-app notice (export_finished · export_expired · export_failed), never on cancel." type ExportJob { id: ID! "The group-scoped human-facing system id (EX-…)." sysId: String! type: String! caption: String! "The FSM state: queued | running | done | cancelled | expired | failed." status: String! "The parent org group (the Saga shape); for an ExportJob parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The owner — the User who started the job; cancel and the download are theirs alone (the system hook cancels on their session’s end). IMMUTABLE at birth." userId: ID! "The signed-in session the job runs under — the EXPORTLOCK aggregate (ONE running export per session); a Session is not a catalog construct, so the id is opaque on the wire. IMMUTABLE at birth." sessionId: ID! "The NORMALIZED plan as JSON text (the validated SearchPlan with its defaults applied; at most 8192 characters) — re-parsed and re-validated at every read. IMMUTABLE at birth." planJson: String! "IMMUTABLE at birth." words: String! "The file format the finish composes — csv (RFC 4180 through the one cell rule: the header = the column union over the whole set, nested leaves as dotted paths, arrays as JSON in the cell) or jsonl (one record per line — the parts’ bytes concatenated). The parts are JSON Lines either way. IMMUTABLE at birth." format: String! "The report arm (📊 THE REPORT ENGINE): the validated ReportSpec as JSON text (at most 12288 characters — the reportRun grammar VERBATIM; its plan equals planJson's), re-parsed at the finish to compose the file (a projection's columns or an aggregate's groups); the job's words are then the report's. IMMUTABLE at birth; null on a plain export." reportJson: String "Machine steps taken so far (0 at birth; stamped by the step lane)." stepsDone: Int! "Records examined so far across every walk and hydrate (0 at birth) — the budget law’s counter." examined: Int! "Parts written so far (0 at birth; +1 per terminal page that kept at least one record)." partCount: Int! "Rows written so far across every part (0 at birth) — the file’s row count at the finish." rowCount: Int! "Bytes written so far across every part (0 at birth) — tracked against the 256 MiB file ceiling; the composed file’s size at the finish." bytes: Int! "True when the run halted before the end — cancelled · expired · refused · the byte ceiling; the file holds what was written." partial: Boolean! "The file’s object key under exports/// — stamped at the finish. Null while live and on a cancel." fileKey: String "The file’s name — --. at the finish instant (ASCII); what exportJobDownload is saved as. Null while live and on a cancel." fileName: String "The file’s expiry (epoch SECONDS = finishedAt + 7 days) — the download’s lazy-TTL gate. Null until the finish." fileTtl: Int "The running instant (UTC ISO-8601 — the clock’s zero). Null while queued." startedAt: String "The terminal instant (UTC ISO-8601). Null while live." finishedAt: String "Why the run stopped short — the executor’s refusal in its teaching voice (the budget, the frontier, the step cap), the byte ceiling, the expiry, the start refusal, or a machine fault’s cause. Null on done." problem: String "The ops/reconcile handle." sfExecutionArn: String } "One page of the exportJobs listing — the records + the opaque resume cursor." type ExportJobPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [ExportJob!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "One entry of a size run: the OptionValue of the run group + its share of the ratio (an integer 0..10000); the rows ride in the caller order = the display order." type SizeRunEntry { optionValueId: ID! share: Int! } "A size run — a RATIO over ONE option dimension (S-M-L-XL 1-2-2-1; a colour run 2 black: 1 white is equally real — any OptionGroup type may carry a run) a buyer fills a matrix with: kept ONCE and reused on every Style that names it (Style.sizeRunId — its group must be in the scheme) or by the dimension itself (OptionGroup.defaultSizeRunId — the org default lives on the dimension); resolution = the style pick, then the group default, then none (the matrix axes carry the resolved id). optionGroupId is IMMUTABLE at birth (a different dimension is a DIFFERENT run: doom + create — the PurchasePack unitsPerPack stance). entries = 1..256 { optionValueId, share } rows — DISTINCT values OF THAT GROUP, every share an integer 0..10000, the shares summing to at least 1, stored in the CALLER order = the display order (a 0-share value rides the run but never receives a unit). sizeRunFill spreads a total over the ratio by the fill rule (largest remainder, ties to the earlier entry, the quantities summing to the total exactly). Doom is blocked while a non-doomed Style or OptionGroup names the run (CONFLICT/REFERENCED naming the holders); deactivate is free. Group-parented (parentId === rootId); sysId SZ-…." type SizeRun { id: ID! "The group-scoped human-facing system id (SZ-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a SizeRun parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The ONE dimension this run is over — set at creation, IMMUTABLE thereafter (a different dimension is a different run: doom + create)." optionGroupId: ID! "The ratio — 1..256 DISTINCT values of the run group with their shares (integers 0..10000, summing to at least 1), in the CALLER order = the display order. Editable WHOLESALE (every value re-gated a member of the group + non-doomed)." entries: [SizeRunEntry!]! "Optional mutable merchant reference code; uniqueness NOT enforced." code: String } "One page of the sizeRuns listing — the records + the opaque resume cursor." type SizeRunPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [SizeRun!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String "The EXACT matched-set size of a FILTERED/SORTED read; null on an unfiltered page." matchCount: Int } "Size-run entry input — the value must belong to the run OptionGroup (parentId === optionGroupId) and be non-doomed; 1..256 entries, DISTINCT values, the shares (integers 0..10000) summing to at least 1." input SizeRunEntryInput { optionValueId: ID! share: Int! } "Create-input for a SizeRun. The tenant (org group) is derived SERVER-SIDE from the principal — NEVER supplied here; optionGroupId is REQUIRED (tenant-scoped, non-doomed) and immutable after birth; entries carry 1..256 DISTINCT values OF THAT GROUP (each non-doomed) with shares summing to at least 1." input NewSizeRunInput { "Optional: when omitted the per-type default applies — the ratio in words — 'Run 1-2-2-1' in the stored order; when supplied it must be non-blank." caption: String "The dimension the run is over — tenant-scoped server-side, non-doomed; IMMUTABLE after birth." optionGroupId: ID! "The ratio (1..256 distinct values of the group, shares summing to at least 1) in display order." entries: [SizeRunEntryInput!]! code: String } "Edit-input for a SizeRun. Every field optional, at least ONE required; supplied fields REPLACE, omitted fields are preserved. code additionally accepts an EXPLICIT null to CLEAR; a supplied entries list replaces WHOLESALE (the MF-d precedent) and is re-gated per value exactly like create. optionGroupId is NOT editable (IMMUTABLE at birth — a different dimension is a different run: doom + create)." input EditSizeRunInput { caption: String "The replacement code, or EXPLICIT null to clear; omitted = unchanged." code: String "The replacement ratio (wholesale) — every value re-gated a member of the group + non-doomed." entries: [SizeRunEntryInput!] } "A TrainingRequirement (🎓 — THE TRAINING PROGRAM, THE WIRE): the owner's rule that people holding a role copied from the canned template roleTemplateKey must hold a VALID TrainingCertificate for the course courseKey — a LIVE play key of the Playbook registry. graceDays (0..365, default 14) = the days after the role grant before the requirement falls due; passMark (1..100, default 80) = the mark a sitting must reach — the STRICTEST rule binding the person for the course wins at an attempt's start. The pair (roleTemplateKey, courseKey) is IMMUTABLE after birth and UNIQUE among the org's non-doomed rules (a duplicate refuses CONFLICT/IDENTITY_TAKEN); at most 100 rules per org (CONFLICT/TRAINING_CAP past it). NOT searchable (no filter roster until the face)." type TrainingRequirement { id: ID! "The group-scoped human-facing system id (TE-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a TrainingRequirement parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The canned role template the rule binds — owner · system_administrator · manager · associate_manager · warehouse_associate · sales_associate · cashier; a person holding ANY role copied from it owes the course. IMMUTABLE at birth." roleTemplateKey: String! "The course — a LIVE play key of the Playbook registry (e.g. connect-a-till). IMMUTABLE at birth." courseKey: String! "Days after the role grant before the requirement is due (0..365; default 14)." graceDays: Int! "The pass mark a sitting must reach (1..100; default 80) — the strictest applicable rule wins." passMark: Int! "What the rule is for (at most 400 characters); optional, set-only." note: String } "One page of the trainingRequirements listing — the records + the opaque resume cursor." type TrainingRequirementPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TrainingRequirement!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The tenant stamps server-side; courseKey must resolve to a live play (VALIDATION naming the arg otherwise); graceDays and passMark default when omitted; roleTemplateKey is one of the seven canned template keys." input NewTrainingRequirementInput { "Optional: when omitted the per-type default applies — the pair (e.g. `cashier · connect-a-till`); when supplied it must be non-blank." caption: String "One of the seven canned role template keys." roleTemplateKey: String! "A live play key." courseKey: String! "0..365; default 14." graceDays: Int "1..100; default 80." passMark: Int "At most 400 characters." note: String } "Edit-input for a TrainingRequirement. Every field optional, at least ONE required; supplied fields REPLACE graceDays, passMark, note and/or caption — at least one; the pair (roleTemplateKey, courseKey) never moves — write a new rule instead." input EditTrainingRequirementInput { caption: String "0..365." graceDays: Int "1..100." passMark: Int "At most 400 characters; set-only." note: String } "A TrainingQuestion (🎓 — THE TRAINING PROGRAM, THE WIRE): ONE multiple-choice question of a course's bank — the prompt (at most 400 characters), 2..6 options (each at most 200 characters), correctIndex (0-based, below the options' count), the explanation shown after a sitting (at most 400 characters), the optional play step it tests and its source (drafted | written). THE STRICT SCHEMA: no unknown keys. active = in the draw · inactive = retired from the draw, kept · doomed. A course's bank holds at most 60 non-doomed questions (CONFLICT/TRAINING_CAP past it). courseKey is IMMUTABLE after birth. A submitted attempt is graded against ITS stored draw — a later edit here never re-grades it. NOT searchable (no filter roster until the face)." type TrainingQuestion { id: ID! "The group-scoped human-facing system id (TQ-…)." sysId: String! type: String! caption: String! "The FSM state: active | inactive | doomed." status: String! "The parent org group; for a TrainingQuestion parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The course — a LIVE play key. IMMUTABLE at birth." courseKey: String! "The play step this question tests (1-based), when one step alone; null when the whole play." stepN: Int "The question (at most 400 characters)." prompt: String! "2..6 options, each at most 200 characters; replaced WHOLESALE on an edit." options: [String!]! "The right option (0-based; below the options count)." correctIndex: Int! "Why that option is right — shown after a sitting (at most 400 characters)." explanation: String! "Where it came from — drafted | written (the assistant's draft the owner kept, or written by hand). IMMUTABLE at birth." source: String! } "One page of the trainingQuestions listing — the records + the opaque resume cursor." type TrainingQuestionPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TrainingQuestion!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "The tenant stamps server-side; courseKey must resolve to a live play and stepN, when given, to one of its steps (VALIDATION otherwise); correctIndex must name one of the options; source is drafted | written." input NewTrainingQuestionInput { "Optional: when omitted the per-type default applies — the prompt cut to the caption cap; when supplied it must be non-blank." caption: String "A live play key." courseKey: String! "The play step it tests (1-based), optional." stepN: Int "At most 400 characters." prompt: String! "2..6 options." options: [String!]! "0-based, below the options count." correctIndex: Int! "At most 400 characters." explanation: String! "drafted | written." source: String! } "Edit-input for a TrainingQuestion. Every field optional, at least ONE required; supplied fields REPLACE prompt, options (WHOLESALE), correctIndex, explanation, stepN and/or caption — at least one; when only one of options/correctIndex moves, the index is checked against the stored options; courseKey and source never move." input EditTrainingQuestionInput { caption: String "The play step it tests (1-based)." stepN: Int "At most 400 characters." prompt: String "Wholesale replacement when supplied." options: [String!] "0-based, below the options count." correctIndex: Int "At most 400 characters." explanation: String } "A TrainingAttempt (🎓 — THE TRAINING PROGRAM, THE WIRE): ONE sitting of a course's test by ONE person — ALWAYS the caller who started it (nobody starts one for someone else). At start the platform draws 10 ACTIVE questions of the course (every active question when fewer; below 3 the start refuses CONFLICT/TRAINING_TOO_FEW_QUESTIONS) and stores EXACTLY that draw (questionIds); passMark is copied from the strictest requirement binding the person for the course, else the default; curriculumVersion is the play's content hash at the sitting. At submit the answers are GRADED SERVER-SIDE against the STORED draw (a later bank edit never re-grades it) — score 0..100, passed = score >= passMark; a PASS mints the TrainingCertificate in the SAME transaction (certificateId). open (live) → submitted (terminal, kept) by the subject · open → doomed (terminal) by manage authority. ONE open sitting per (person, course) — a second start refuses CONFLICT/TRAINING_ATTEMPT_OPEN; at most 5 sittings per (person, course) per UTC day (CONFLICT/TRAINING_CAP). The by-id read answers the subject or the training-manage right; the listing is the manage right's. NOT searchable." type TrainingAttempt { id: ID! "The group-scoped human-facing system id (TT-…)." sysId: String! type: String! caption: String! "The FSM state: open | submitted | doomed." status: String! "The parent org group; for a TrainingAttempt parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The subject — the User who started the sitting; ALWAYS the caller. IMMUTABLE at birth." userId: ID! "The organization the sitting was started in (the session’s acting org) — the progress record’s second coordinate. IMMUTABLE at birth." orgId: ID! "The course — a live play key. IMMUTABLE at birth." courseKey: String! "THE DRAW — 3..10 question ids drawn from the ACTIVE bank at start, in the order asked; the grade is taken against exactly these. IMMUTABLE at birth." questionIds: [ID!]! "One option index per drawn question, in the draw order — set ONCE at submit; null while open or doomed." answers: [Int!] "The grade 0..100 (rounded) — set at submit; null while open or doomed." score: Int "score >= passMark — set at submit; null while open or doomed." passed: Boolean "Copied at start from the strictest requirement binding the person for the course, else the default 80. IMMUTABLE at birth." passMark: Int! "The start instant (UTC ISO-8601). IMMUTABLE at birth." startedAt: String! "The submit instant (UTC ISO-8601); null while open or doomed." submittedAt: String "The play’s content hash at the sitting (16 hex — sha-256 over its title, line and the steps’ words); ’s refresh rule compares it. IMMUTABLE at birth." curriculumVersion: String! "The certificate a PASSING submit minted in the same transaction; null on a fail, while open, or when doomed." certificateId: ID } "One page of the trainingAttempts listing — the records + the opaque resume cursor." type TrainingAttemptPage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TrainingAttempt!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "A TrainingCertificate (🎓 — THE TRAINING PROGRAM, THE WIRE): the platform's own record that a person passed a course — MINTED BY THE API at a passing submit, in the SAME transaction as the attempt's transition, NEVER by a client (no create op exists on the wire). The holder (userId), the course, the passing sitting (attemptId), the score and the pass mark, the issue instant and the course's content version (curriculumVersion). valid (live) → revoked (terminal; manage authority, a reason required) · valid → superseded (terminal; SYSTEM-ONLY — the person's next pass of the same course supersedes it and keeps it as history). expiresAt is null — 's refresh rule sets it. The by-id read answers the holder or the training-manage right; the listing is the manage right's (revoked drops from it, superseded stays as history; both stay point-readable). NOT searchable." type TrainingCertificate { id: ID! "The group-scoped human-facing system id (TC-…)." sysId: String! type: String! caption: String! "The FSM state: valid | superseded | revoked." status: String! "The parent org group; for a TrainingCertificate parentId === rootId." parentId: ID! "The org-group family root." rootId: ID! createdAt: String! updatedAt: String! revisionNum: Int! "The OCC revision token — supply it on every mutation of this record; rotates on every write." revision: ID! "The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption." refCaptions: [RefCaption!]! "The holder. IMMUTABLE." userId: ID! "The course — a live play key. IMMUTABLE." courseKey: String! "The passing sitting. IMMUTABLE." attemptId: ID! "The sitting’s grade 0..100 — stored on every certificate; NULL on the wire to a NON-subject reader when training.score_visibility is 0 (🎓; the holder always reads it." score: Int "The pass mark the sitting had to reach." passMark: Int! "The issue instant (UTC ISO-8601) — the mint transaction’s clock." issuedAt: String! "The play’s content hash the course was passed on (16 hex) — ’s refresh rule compares it to today’s." curriculumVersion: String! "null — the refresh rule is CONTENT-based (refreshDue), never time-based (🎓 (b))." expiresAt: String "DERIVED AT READ TIME, never stored (the twin rule — 🎓): true when the course’s CURRENT content hash differs from curriculumVersion (or the play is gone) — sit again to refresh; the api compares through the kit’s course facts." refreshDue: Boolean! } "One page of the trainingCertificates listing — the records + the opaque resume cursor." type TrainingCertificatePage { "The page's records (doomed drops per page, a page may hold FEWER than `limit`; walk until `nextToken` is null)." items: [TrainingCertificate!]! "Present ⇒ more may remain (pass back verbatim as `nextToken`); null ⇒ the listing is complete. Opaque + tenant-bound." nextToken: String } "One opening of a sealed staff-activity trail: the ledger row every door writes." type SupportTrailUnseal { id: ID! at: String! "merchant (the owner’s own ask) or support (a platform support agent against a ticket)." door: String! "The merchant door: the asking owner’s user id; the support door: the platform principal’s name." actor: String! subjectUserId: ID! from: String! to: String! reason: String ticketRef: String "How many sealed rows the window held when it was opened." rowsReturned: Int! } "One unsealed trail row — what one API call said about what the person was doing (every value a vocabulary word, a number, an instant or an id — never free text)." type SupportTrailRow { at: String! app: String! appVersion: String screen: String action: String op: String type: String outcome: String! ms: Int! callId: ID! orgId: ID! sessionId: ID! device: ID } "The merchant door’s answer: the opening as recorded + the timeline in time order + the rows that refused to open (counted, never hidden)." type UserActivityTrail { unseal: SupportTrailUnseal! rows: [SupportTrailRow!]! unreadable: Int! } type Query { "A liveness read — no contract version required (reads may omit, SPEC_ENVELOPE)." health: String! "The current authenticated principal, or null when the call is unauthenticated." me: Principal "Caption typeahead within the caller's OWN org-group family; requires authentication. Scoped server-side to the principal's rootId (never cross-tenant); the prefix folds case/diacritic-insensitively; limit defaults + clamps server-side." search(type: SearchableType!, prefix: String!, limit: Int): [SearchHit!]! "ONE search over EVERY kind of record you may read — a word, a code or an id finds products, vendors, contacts and more, grouped by kind. Requires authentication; scoped server-side to the principal's rootId (never cross-tenant). The prefix is ONE word (a space inside refuses VALIDATION/INVALID — the face sends one word at a time; slice 3's grammar compiles phrases) of at least 2 folded characters (a one-character prefix is refused, never searched) and at most the caption length; it folds case- and diacritic-insensitively and matches the START of a caption word, the sysId or the record's own code. THE LENS: only the kinds whose plural read your roles permit ever answer — a hit of any other kind is dropped before the page is cut (a cashier never sees a collaborator's name in a suggestion). first defaults to 20 and clamps to 50; more says rows remained. The variant's SKU is NOT here by the catalogue ruling — resolveIdentifier is its exact door." searchAll(prefix: String!, first: Int): SearchAllPage! "The verification mechanism: the FULL effective-permission map for an in-tenant (user, organization) pair — every registry operation evaluated by the SAME flat algorithm the future gate uses (default-DENY → union allow across the user's ACTIVE roles at the org → disallow-ALWAYS-wins), each entry attributing its contributing descriptors to their roles. Requires authentication; reads null when the user OR the organization is cross-tenant or absent. Previews DESCRIPTOR evaluation ONLY — no capability/dark-org/lifecycle composition (the ruled cutover slice)." effectivePermissions(userId: ID!, organizationId: ID!): EffectivePermissions "YOUR OWN effective permissions at the organization you are acting in — the SAME evaluator and the SAME answer shape as effectivePermissions (roles · operations over the WHOLE registry), computed over the session's own user and acting organization (no arguments). SELF on the USER plane — every principal keeps it (an API key or a collaborator has no own user → AUTHZ/FORBIDDEN, never a synthetic answer); the office's lens read, so every reader's course narrows to what their role can run." myEffectivePermissions: EffectivePermissions! "THE PEEK SWITCH read: the SAME compile as effectivePermissions over ONE in-tenant role — every registry operation evaluated for that role alone. READ semantics: a cross-tenant or absent role/organization reads null — existence never leaks." rolePermissions(roleId: ID!, organizationId: ID!): EffectivePermissions "THE TRAIL LEDGER: every opening of the caller’s group’s sealed staff-activity trails — who opened it, which door (merchant · support), which user, which window, the ticket or the reason, how many rows — newest first, optionally windowed by ISO instants. OWNER-ONLY (the A19_TRAIL area). The read model expires with the trail (90 days); every opening is also a permanent log event." supportTrailUnseals(from: String, to: String): [SupportTrailUnseal!]! "Reserved for the platform; not available to API keys." loginChoices(identifier: String!, password: String!): LoginChoicesResult! "Reserved for the platform; not available to API keys." passwordResetContext(token: String!): PasswordResetContext! "An Organization by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." organization(id: ID!): Organization "The caller's org-group family's ACTIVE LISTING of Organizations — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Organization roster: `caption` (text) · `status` (enum) · `code` (text) · `legalName` (text) · `jurisdiction` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." organizations(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrganizationPage! "The system-shipped IMMUTABLE Characteristic templates; registry data, identical for every tenant. Requires authentication." cannedCharacteristics: [CannedCharacteristic!]! "The canned UoM registry. Requires authentication." cannedUoms: [CannedUom!]! "A variant's identifier ledger: current + superseded entries, VOIDED excluded, most-recent-first; kind/organizationId filters compose. Requires authentication; the variant is tenant-scoped server-side." variantIdentifiers(variantId: ID!, kind: String, organizationId: ID): [IdentifierEntry!]! "The locked resolution: current + ledgered values as ONE namespace per kind — a historical match still resolves to its variant (outdated-flagged); ALL matches, most-recent-first. organizationId REQUIRED for plu/gtin, REFUSED for sku. ZERO matches → NOT_FOUND/IDENTIFIER. Requires authentication." resolveIdentifier(kind: String!, value: String!, organizationId: ID): [IdentifierResolutionMatch!]! "THE MEMBERSHIP EVALUATION: a collection's products = its pins UNION (predicate matches MINUS exclusions), gated to ACTIVE products of ACTIVE styles, ordered per sortMode (newest | price-asc | price-desc | manual-pins-first). A static collection reads as its ACTIVE members' surviving products by ordinal (all pinned). A STAGED (inactive) collection EVALUATES — previewing is what staging is for; a doomed one reads as an empty list. Requires authentication; the collection is tenant-scoped server-side." collectionProducts(collectionId: ID!): [CollectionProductHit!]! "THE AGENT CATALOG — search: what the AgentChannel LISTS (the listing rule — the ACTIVE listed Collections' active products, active variants minus the veto list, ranged + priced at the selling location NOW, the PriceList plane when set), matched by query words (title · description · code · variant titles · codes · SKUs; all words, case/diacritic-folded) and/or filters (category captions OR-matched; price bounds in the listing currency's minor units), paged (limit default 10, max 50; an opaque cursor bound to the criteria). At least one of query/categories/price is required. The agent_platform principal reads ONLY its own channel (any other id → AUTHZ/FORBIDDEN); staff planes read any channel of the group (a missing/foreign channel → NOT_FOUND). This is EXACTLY what an agent platform sees on the shop's host — the merchant's preview." agentChannelCatalogSearch(agentChannelId: ID!, query: String, categories: [String!], priceMinMinor: Int, priceMaxMinor: Int, limit: Int, cursor: String): AgentChannelCatalogPage! "THE AGENT CATALOG — lookup: resolve up to 50 identifiers (a listed Product id → its featured first variant · a listed Variant id · a listed variant's SKU or barcode → that variant exactly) to listed products whose variants carry inputs; identifiers reaching nothing listed are named in notFound (never an error — the spec's partial-success shape). The same principal law as the search." agentChannelCatalogLookup(agentChannelId: ID!, ids: [String!]!): AgentChannelCatalogLookup! "THE AGENT CATALOG — product detail: one identifier (product · variant · SKU · barcode) → the listed product with its variants narrowed by the effective selections (a variant identifier fixes them; else the request's selected, relaxed from the END of preferences until a variant matches), every option value marked available/exists relative to them. product is null when nothing listed matches. The same principal law as the search." agentChannelCatalogProduct(agentChannelId: ID!, id: String!, selected: [AgentCatalogSelectedOptionInput!], preferences: [String!]): AgentChannelCatalogDetail! "THE AGENT CHECKOUT — read: one agent checkout's quote view at NOW. The agent_platform principal reads its OWN channel's checkouts opened by ITS platform (any other → the uniform NOT_FOUND); staff (read) read any checkout of their group's channels. A checkout of another channel, another platform, or an Order that is not an agent checkout is the SAME uniform NOT_FOUND." agentChannelCheckout(agentChannelId: ID!, orderId: ID!, linkedConsumerId: ID): AgentCheckout! "THE AGENT ORDER — read: one agent-originated SALE as the platform reads it (the released Order's words). The agent_platform principal reads the orders ITS platform originated on ITS channel (any other → the uniform NOT_FOUND); staff read any of their group's agent sales — the merchant's own preview." agentChannelOrder(agentChannelId: ID!, orderId: ID!, linkedConsumerId: ID): AgentOrder! "The Stock Card: one InventoryItem's posted movement entries, NEWEST-FIRST + bounded (limit defaults 50, clamps 1..200; before = an EXCLUSIVE upper entry-id bound — v7 ids are time-ordered, the older-page cursor). Voided entries excluded. Requires authentication; the II is tenant-scoped server-side." stockCard(inventoryItemId: ID!, limit: Int, before: ID): [InventoryEntry!]! "The two-way reconciliation read: recompute the bucket balances from the ACTIVE Stock-Card entries and compare against the II cached balances — the bounded per-II verify (the standing auditor is the catalogued escalation). Since ALSO reconciles the StockRecord shards against the relocate entries and reports the binned/un-binned split. Requires authentication; reads null on a cross-tenant/missing id." verifyInventoryItem(inventoryItemId: ID!): InventoryVerification "One InventoryItem StockRecord shard rows — where its stock sits in bins (zero rows = everything un-binned). Requires authentication; a cross-tenant/missing id reads as an empty list; a doomed item keeps READABLE shards." stockRecords(inventoryItemId: ID!): [StockRecord!]! "One Bin StockRecord rows across items. Requires authentication; a cross-tenant/missing id reads as an empty list." binStock(binId: ID!): [StockRecord!]! "The derived INBOUND view: every receivable PO (issued / acknowledged / partially_received) flattened to its outstanding lines (ordered − received > 0), shaped {po, line, variant, LF, outstandingQty, expectedArrivalAt}. DERIVED at read off the purchase_orders walk — never stored; fully-received lines and terminal history drop. Requires authentication; scoped server-side to the principal's rootId." expectedReceipts: [ExpectedReceipt!]! "ONE PurchaseOrder's own lines, lineNo-ORDERED + born-paginated. purchaseOrderId is the REQUIRED anchor (tenant-scoped — a cross-tenant/missing order refuses NOT_FOUND, never an empty page). 'nextToken' = the prior page's cursor, verbatim (opaque; malformed/foreign → VALIDATION/INVALID). Requires authentication." purchaseOrderLines(purchaseOrderId: ID!, filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): PurchaseOrderLinePage! "ONE Receipt's own lines, lineNo-ORDERED + born-paginated. receiptId is the REQUIRED anchor (tenant-scoped — a cross-tenant/missing receipt refuses NOT_FOUND, never an empty page). 'nextToken' = the prior page's cursor, verbatim (opaque; malformed/foreign → VALIDATION/INVALID). Requires authentication." receiptLines(receiptId: ID!, filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ReceiptLinePage! "The resolution DIAGNOSTIC for one (variant × LF): the effective parameter set + per-parameter provenance (config + the specificity trace) + every matched config. REFUSES VALIDATION/INVALID naming both configs, the parameter, and the cure when two equal-specificity configs set the same parameter (the season multi-membership residual — lean, no silent winner). Reads null when the variant or LF is missing/cross-tenant. Requires authentication." replenishmentParameters(variantId: ID!, logicalFacilityId: ID!): ReplenishmentParameterResolution "THE BUY SUGGESTER: scope REQUIRED bounded (EXACTLY one of logicalFacilityId ⊕ organizationId; optional orgVendorId/categoryId/styleId/variantIds narrows). Per ACTIVE stocked junction in scope: position = available + in_transit + on-order (the expectedReceipts walk; held/damaged excluded) vs the resolved min/safety/days-of-supply levels; deficits round UP through the effective MOQ + reorder multiple (pack/forced — the machinery) and group by OrgVendor into DRAFT-PO-SHAPED payloads (realization-ready VERBATIM for createPurchaseOrder, which re-gates authoritatively — the engine never outruns the gates). orderMinimum shortfalls are ANNOTATED, never padded. URGENT deficits (velocity-dependent) couple into transfer-now + backfill-PO pairs. Books with no live OVI land in gaps as no-ovi. DERIVED at read, never stored. Requires authentication." replenishmentSuggestions(logicalFacilityId: ID, organizationId: ID, orgVendorId: ID, categoryId: ID, styleId: ID, variantIds: [ID!]): ReplenishmentSuggestionsResult! "THE PULL SUGGESTER: deficits at the destination filled from donors with GENUINE excess (available − the donor's OWN resolved target − reserveFloor > 0 — exactly at target+reserve is NOT excess; transferableExcess honored) in the lane order (never dropped · always first · ranked · geodistance defaults); TR-SHAPED payloads, one per donor (pull semantics — the TR doc IS the demand doc). DERIVED at read. Requires authentication." rebalanceSuggestions(destinationLogicalFacilityId: ID!, variantIds: [ID!]): RebalanceSuggestionsResult! "THE PUSH SUGGESTER: the hub's genuine excess fair-shared across OTHER LFs holding the variant by their resolved allocationWeight (largest remainder, deterministic); destinations with no resolved weight land in gaps as no-weights; never-lanes out of the hub drop their destination. Transfer-SHAPED payloads (push semantics — the.1 doc; lines name the SOURCE InventoryItem). DERIVED at read. Requires authentication." allocationSuggestions(sourceLogicalFacilityId: ID!, variantIds: [ID!]): AllocationSuggestionsResult! "The resolved sourcing matrix into ONE destination: every ACTIVE source LF as a row — stored lanes (never/always/ranked) + the sparse geodistance DEFAULT ordering (LF→PF→PFL.geo; a geo-absent side ranks LAST flagged no-geo; same-PFL light out-ranks shipped at equal distance). never entries are SHOWN position-less (excluded from consideration — an INACTIVE lane is ABSENT, not never). DERIVED at read. Requires authentication." transferLaneRanking(destinationLogicalFacilityId: ID!): [TransferLaneRankingEntry!]! "THE ABC CLASSIFIER: value × velocity scores with registry cut lines (A < 80% cumulative share, B < 95%, else C); scope REQUIRED bounded (EXACTLY one of logicalFacilityId ⊕ organizationId); abcClassOverride pins a book's class; a zero-velocity scope orders by the value axis alone (scoreBasis: value — -i, disclosed). ARMS the.2 count-scope abcClass filter. DERIVED at read. Requires authentication." abcClasses(logicalFacilityId: ID, organizationId: ID): [AbcClassEntry!]! "THE MATRIX READ: ONE Style's live cells at ONE LogicalFacility — on hand · reserved · available · on order per Variant, the axes in scheme order and every axis's values in ordinal order, the cells axis-major. Both refs tenant-scoped (a foreign/missing Style or LogicalFacility refuses NOT_FOUND). Bounded by the style: at most 1000 live cells — over refuses VALIDATION naming the count and the cap, never a truncated grid. Doomed products/variants are not cells; inactive ones are. A cell with no (variant × LF) InventoryItem reads zeros with inventoryItemId null. Requires authentication." styleStockMatrix(styleId: ID!, logicalFacilityId: ID!): StyleStockMatrix! "THE FILL: spread a total over a SizeRun's ratio — whole units by the largest-remainder law (each entry floor(total × share ÷ Σ shares), the remainder one unit at a time to the largest fractional parts, ties to the EARLIER entry; Σ = total exactly; a 0-share entry never receives a unit), answered in the run's stored order. The run tenant-scoped (a foreign/missing run refuses NOT_FOUND); total an integer 0..1000000000 (else VALIDATION). A pure read — nothing changes. Requires authentication." sizeRunFill(sizeRunId: ID!, total: Int!): [SizeRunFillCell!]! "THE ON-ORDER AUDIT: ONE page of your tenant's stock junctions checked against the derived truth — for each InventoryItem the STORED onOrderQty (maintained by the purchase-order walks + the receipt post) beside the figure DERIVED from the receivable purchase orders' open lines (computed ONCE per call), answering ONLY the rows that differ, the page's driftCount, and the cursor for the next page. Doomed junctions are skipped. An order still walking (issuing / cancelling / closing) reads as drift until it lands. A READ — nothing written; repairInventoryOnOrder stamps one cell. 'limit' bounds the page; 'nextToken' = the prior page's cursor, verbatim (opaque). Requires authentication; scoped server-side to the principal's rootId." inventoryOnOrderAudit(limit: Int, nextToken: String): InventoryOnOrderAuditPage! "The CashEntry ledger of ONE TillSession, NEWEST-FIRST + bounded: 'limit' clamps server-side; 'before' = the prior page's oldest entry id (exclusive — walk backward in time). With the tillSession GET (cached drawerTotals + counted/overShort) this IS the X/Z-report data (rendered artifacts = the reports family). Requires authentication; the session is tenant-scoped server-side." drawerLedger(tillSessionId: ID!, limit: Int, before: ID): [CashEntry!]! "The Tender ledger of ONE Order, NEWEST-FIRST + bounded: 'limit' clamps server-side; 'before' = the prior page's oldest tender id (exclusive). With the order GET (tenderedNetMinor/tipTotalMinor/paymentState) this IS the settlement story — sale tenders + refund tenders, Return-ref'd. Requires authentication; the order is tenant-scoped server-side." orderTenders(orderId: ID!, limit: Int, before: ID): [Tender!]! "Resolve the EFFECTIVE FX rate for (fromCurrency → the org's default currency) at an instant. 'at' ABSENT = the server's now (past instants are legal — historical reconstruction is a READ). What this quotes is EXACTLY what a foreign_cash tender applies. No covering record / a dangling adjustment chain refuses CONFLICT/NO_EFFECTIVE_RATE (retryable — create the rate, then retry). Requires authentication; the org + LF are tenant-scoped server-side." resolveFxRate(fromCurrency: String!, organizationId: ID!, logicalFacilityId: ID, at: String): FxResolution! "Resolve the EFFECTIVE policy value for (scope × key) at an instant. 'at' ABSENT = the server's now (past instants are legal — historical reconstruction is a READ). What this quotes is EXACTLY what the platform applies. An unknown key refuses naming the registry roster. Requires authentication; the org + LF are tenant-scoped server-side. Template class A18_POLICY (sensitive config — owner/manager)." resolvePolicyValue(key: String!, organizationId: ID!, logicalFacilityId: ID, at: String): PolicyResolution! "A DOOMED holder RESOLVES with its status visible (the BURN law — the code stays on its corpse forever; the tender lanes refuse on status); an unknown/malformed code refuses NOT_FOUND/CONSTRUCT. CONTRAST coupons: no coupon-resolve op exists (codes enter only via apply). Requires authentication; tenant-scoped server-side." resolveStoredValueInstrument(code: String!): StoredValueInstrument! "The StoredValueEntry ledger of ONE instrument, NEWEST-FIRST + bounded: 'limit' clamps server-side; 'before' = the prior page's oldest entry id (exclusive). With the instrument GET (cached balanceMinor — stamped in the SAME transaction as every entry) this IS the balance story. Requires authentication; the instrument is tenant-scoped server-side." storedValueLedger(instrumentId: ID!, limit: Int, before: ID): [StoredValueEntry!]! "The LoyaltyPointsEntry ledger of ONE member, NEWEST-FIRST + bounded: 'limit' clamps server-side; 'before' = the prior page's oldest entry id (exclusive). With the member GET (cached pointsBalance — stamped in the SAME transaction as every entry) this IS the points story (earn/redeem/redeem_reversal/clawback/adjust, -ref'd to their orders/returns with per-line details). Requires authentication; the member is tenant-scoped server-side." loyaltyLedger(memberId: ID!, limit: Int, before: ID): [LoyaltyPointsEntry!]! "from/to are the half-open period bounds over createdAt (UTC ISO-8601). 'nextToken' = the prior page's cursor. Requires authentication; tenant-scoped server-side." commissionEntryList(agentUserId: ID, from: String, to: String, limit: Int, nextToken: String): CommissionEntryPage! "The AffiliateEntry ledger read." affiliateEntryList(affiliateId: ID, from: String, to: String, limit: Int, nextToken: String): AffiliateEntryPage! "The commission payout report: signed rows per (agent × currency) over entries createdAt ∈ [from, to) — earned/clawedBack/payable/entryCount; late claws land in THEIR OWN period as negative rows (append-only — close periods after the return window); agentUserId narrows to one agent. NO posting state — payroll is external BY DESIGN." commissionPayoutReport(from: String!, to: String!, agentUserId: ID, limit: Int, nextToken: String): CommissionPayoutRowPage! "The affiliate payout twin: signed rows per (affiliate × currency)." affiliatePayoutReport(from: String!, to: String!, affiliateId: ID, limit: Int, nextToken: String): CommissionPayoutRowPage! "The AREntry ledger of ONE OrgCustomer house account, NEWEST-FIRST + born-paginated. from/to are the half-open period bounds over createdAt (UTC ISO-8601). 'nextToken' = the prior page's cursor. With the OrgCustomer GET (cached arBalanceMinor — stamped in the SAME transaction as every post) this IS the debt story (charge/payment/credit_memo/writeoff, -ref'd to their orders/tenders/returns/notes). Requires authentication; the account is tenant-scoped server-side." arLedger(orgCustomerId: ID!, from: String, to: String, limit: Int, nextToken: String): ArEntryPage! "The receivables aging report: the 5 fixed buckets (not_yet_due / 1-30 / 31-60 / 61-90 / 90+ days past dueAt — raw-UTC day math, the LIVE posture) over OPEN charges via the O(open) frontier walk (the head at its cached partial, later charges at face), each {count, totalMinor}, + asOf + arCurrency + the cached balance (Σ buckets == arBalanceMinor BY CONSTRUCTION). With arLedger this IS the lock's aging/statements DATA plane (statement DOCUMENTS + dunning =). Requires authentication; tenant-scoped server-side." arAging(orgCustomerId: ID!): ArAgingReport! "The 7 canned role templates: copy via copyCannedRole. NOT a construct list (bounded 7 forever — the transferLanes roster class; untouched). Requires authentication." cannedRoles: [CannedRole!]! "Reserved for the platform; not available to API keys." collaboratorMe: Collaborator! "Reserved for the platform; not available to API keys." collaboratorLoginChoices(orgId: ID!, email: String!, password: String!): CollaboratorLoginChoicesResult! "Reserved for the platform; not available to API keys." myCollaboratorAccess: CollaboratorAccess! "Reserved for the platform; not available to API keys." consumerMe: Consumer! "The 6 canned consent-purpose templates: copy via copyCannedConsentPurpose. NOT a construct list (bounded 6 — the cannedRoles roster class; untouched). Requires authentication." cannedConsentPurposes: [CannedConsentPurpose!]! "Reserved for the platform; not available to API keys." myConsents(limit: Int, nextToken: String): MyConsentRowPage! "ONE case's message thread, OLDEST-FIRST + born-paginated internal notes). caseId is the REQUIRED anchor (tenant-scoped — a cross-tenant/missing case refuses NOT_FOUND). 'nextToken' = the prior page's cursor, verbatim (opaque + case-bound; malformed/foreign → VALIDATION/INVALID). Requires authentication." caseMessages(caseId: ID!, limit: Int, nextToken: String): CaseMessagePage! "ONE consumer's cases, NEWEST-FIRST + born-paginated. consumerId is the REQUIRED anchor (tenant-scoped). Cancelled drops per page; closed history stays. Requires authentication." casesByConsumer(consumerId: ID!, limit: Int, nextToken: String): CsCasePage! "Reserved for the platform; not available to API keys." myCases(limit: Int, nextToken: String): CsCasePage! "Reserved for the platform; not available to API keys." myCase(id: ID!): CsCase! "Reserved for the platform; not available to API keys." myCaseMessages(caseId: ID!, limit: Int, nextToken: String): CaseMessagePage! "ONE registry's item rows, OLDEST-FIRST + born-paginated. registryId is the REQUIRED anchor (tenant-scoped). Doomed (removed) rows stay listed — history. Requires authentication." registryItems(registryId: ID!, limit: Int, nextToken: String): RegistryItemPage! "ONE registry's fulfillment facts, OLDEST-FIRST + born-paginated: with the item rows this IS the purchased/remaining story (purchased = Σ qty; remaining floors 0). registryId is the REQUIRED anchor. Requires authentication." registryFulfillments(registryId: ID!, limit: Int, nextToken: String): RegistryFulfillmentPage! "ONE consumer's registries, NEWEST-FIRST + born-paginated. consumerId is the REQUIRED anchor (tenant-scoped). Doomed drops per page; closed/expired history stays. Requires authentication." registriesByConsumer(consumerId: ID!, limit: Int, nextToken: String): GiftRegistryPage! "Reserved for the platform; not available to API keys." myGiftRegistries(limit: Int, nextToken: String): GiftRegistryPage! "Reserved for the platform; not available to API keys." myGiftRegistry(id: ID!): GiftRegistry! "Reserved for the platform; not available to API keys." myRegistryItems(registryId: ID!, limit: Int, nextToken: String): RegistryItemPage! "Reserved for the platform; not available to API keys." myProductReview(productId: ID!): Review "The group wallet's token-ledger facts, NEWEST-FIRST + born-paginated. With the wallet GET (cached balance) this IS the billing transparency surface: balance == Σ entries EXACTLY. Requires authentication. Template class A16_BILLING (hand-derived v23)." tokenEntries(limit: Int, nextToken: String): TokenEntryPage! "The caller group's OWN platform referral earnings, NEWEST-FIRST + bounded. SELF-group BY CONSTRUCTION. Each entry snapshots rate + basis — the earnings transparency surface; the wallet's affiliateCreditCents is the live spendable Σ. Requires authentication. Template class A16_BILLING (hand-derived v23)." affiliateAccruals(limit: Int, before: ID): [AffiliateAccrual!]! "The caller group's kernel BLOCKS, NEWEST-first + bounded. SELF-group BY CONSTRUCTION; a block-less group answers. The transfer surface reads this list (transferable = approved | transfer_denied, settled ≥ 90 days). Requires authentication. Template class A16_BILLING (hand-derived v94)." kernelBlocks(limit: Int, before: ID): [KernelBlock!]! "The caller group's Stripe revshare give-back standing. The report = the derived tenure clock + the earned tier + the next rung + the earned USD ledger (NEWEST-FIRST + bounded — the affiliateAccruals page shape). SELF-group BY CONSTRUCTION (no target arg). Requires authentication. Template class A16_BILLING (hand-derived v91)." giveBack(limit: Int, before: ID): GiveBackReport! "The caller group's handholding-plan report. SELF-group BY CONSTRUCTION (no target arg); a plan-less group answers standing 'none' with its honest classing (a quiet group is Small). Requires authentication. Template class A16_BILLING (hand-derived v93)." supportPlan: SupportPlanReport! "The caller group's OWN referral roster: every business that signed up with your referral code, NEWEST-first, with its code, its standing (pending | approved | denied — derived from the referred group's own record, the one source of truth), when it joined and when it was decided. The optional status filter narrows to one standing (pending | approved | denied — any other word refuses VALIDATION/INVALID; absent = every referred signup). SELF-group BY KEY CONSTRUCTION; a group that referred nobody answers. Earning begins at the next billing cycle AFTER approval — months that pass while pending never accrue; a denied referral never earns; the referred business's own discount rides from birth regardless; every decision also reaches your owners as a notice + a mail. Requires authentication. Template class A16_BILLING (hand-derived v96)." referredSignups(status: String): [ReferredSignup!]! "The caller group's OWN referral performance report: counts of referred businesses by standing (+ gone · earning), lifetime totals by kind (earned ≥ 0 · applied/clawback ≤ 0 — SIGNED like the ledger), the spendable credit, the NEWEST 12 months that carry entries, and one page of referred businesses each with months paid · latest billed cycle · usage-window months left · earned · reversed. SELF-group BY KEY CONSTRUCTION (no target arg); a group that referred nobody answers the zero report. referrals NEWEST-first by the referred group's id — limit clamps [1,200] default 50, before pages backward by that id (the affiliateAccruals grammar); the counts and totals are page-independent. Requires authentication. Template class A16_BILLING (hand-derived v97)." referralReport(limit: Int, before: ID): ReferralReport! "Reserved for the platform; not available to API keys." changeRequest(id: ID!): ChangeRequest "Reserved for the platform; not available to API keys." changeRequests(limit: Int, nextToken: String): ChangeRequestPage! "No further notes." myChangeRequests(limit: Int, nextToken: String): ChangeRequestPage! "No further notes." myChangeRequest(id: ID!): ChangeRequest! "Reserved for the platform; not available to API keys." referralCode(code: String!): ReferralCodeDetail! "Reserved for the platform; not available to API keys." referralCodes(limit: Int, nextToken: String): ReferralCodePage! "The calling principal's OWN live tasks, NEWEST-FIRST + born-paginated. SELF-scoped BY CONSTRUCTION — no userId argument exists. Requires authentication." myTasks(limit: Int, nextToken: String): TaskPage! "ONE team's live tasks, NEWEST-FIRST + born-paginated. teamId is the REQUIRED anchor (tenant-scoped — a cross-tenant/missing team refuses NOT_FOUND). Requires authentication." teamTasks(teamId: ID!, limit: Int, nextToken: String): TaskPage! "The tasks ref-bound to ONE construct, NEWEST-FIRST + born-paginated. constructId = any in-tenant construct id (tenant-scoped). Requires authentication." tasksByConstruct(constructId: ID!, limit: Int, nextToken: String): TaskPage! "ONE construct's note thread, OLDEST-FIRST + born-paginated. targetConstructId is the REQUIRED anchor (tenant-scoped — a cross-tenant/missing target refuses NOT_FOUND). Requires authentication." notes(targetConstructId: ID!, limit: Int, nextToken: String): NotePage! "The calling principal's raw bookmark rows. scope defaults ALL. Bounded by the per-subject cap. Requires authentication." myBookmarks(scope: FeedScope): [BookmarkRef!]! "The composed bookmark feed: the subjects' bookmarks sorted by most-recent activity (max of target updates, boosts, due pops), quiet ones sinking; a doomed/purged target drops. A NOTE card renders COMPOSED — 'a note on ⟨target caption⟩: ⟨title or first line⟩' — and carries its anchor pair. SELF-scoped BY CONSTRUCTION. limit defaults 50, clamps at 100. Requires authentication." myFeed(scope: FeedScope, limit: Int): [FeedCard!]! "Your merged inbox. limit defaults 50, clamps at 100. Requires authentication." myMessages(limit: Int, nextToken: String): MessageRefPage! "Your notices. limit defaults 50, clamps at 100. Requires authentication." myNotifications(limit: Int, nextToken: String): NotificationRefPage! "What shipped, NEWEST first (🆕 — THE CHANGES TAB): the platform's release record in the merchant's words, off the bundled table — the same rows the office's What's new tab shows. since: a UTC calendar day YYYY-MM-DD — the rows on or after it (malformed → VALIDATION/INVALID); absent = the last 90 days. limit: the house page size (default 100, clamps at 200). nextToken: a prior page's cursor VERBATIM (opaque; a foreign cursor → VALIDATION/INVALID). A SELF read — every signed-in person, every role; an integration key reads it too (release notes are public-grade). Requires authentication." changes(since: String, limit: Int, nextToken: String): ChangePage! "Every email the platform sent to YOUR account: newest-first born-paginated; SELF by construction, no subject argument exists; visible from EVERY workspace of the account. limit defaults 100, clamps at 200 (the shared list-page law). Requires authentication." myMailLedger(limit: Int, nextToken: String): MailLedgerPage! "Requires authentication." mailByRef(ref: String!): MailLedgerEntry! "Your tenant's event bus. constructTypes filters to those construct types (the type chips — unknown names refuse VALIDATION); includeSystem (default false) admits the platform's OWN changes — the system actor's rows and actor-less rows — which the walk otherwise folds, so a page counts the rows a reader will SEE; limit defaults 50, clamps at 100. Requires authentication." orgBus(limit: Int, nextToken: String, constructTypes: [String!], includeSystem: Boolean): OrgBusEntryPage! "The ACTING org's operational layout in ONE call — Organization → PhysicalFacilities (each naming its referenced location site) → LogicalFacilities → Registers, every level sysId-ordered ('map my org' answered whole; the orgBus synopsis posture: opening a record still enforces per-op capability). No arguments — the session's acting org IS the subject. Requires authentication." orgLayout: OrgLayout! "One batch's child codes with their redemption status, in mint order, born-paginated (limit defaults 50, clamps 1..100; walk until nextToken is null). The batch must exist in YOUR org group. Requires authentication." couponBatchCodes(batchId: ID!, limit: Int, nextToken: String): CouponBatchCodePage! "One segment's members, consumerId-ordered, born-paginated (limit defaults 50, clamps 1..100; walk until nextToken is null). The segment must exist in YOUR org group. Requires authentication." segmentMembers(segmentId: ID!, limit: Int, nextToken: String): SegmentMemberPage! "The feed must exist in YOUR group. Template class (integration config — off the floor)." feedSubscriptionRuns(feedSubscriptionId: ID!): [FeedRunRef!]! "Validate + resolve ONE connector authorize request for the consent face: the client's words + the redirect host + YOUR eligible orgs. EVERY invalid request refuses typed (the face SHOWS the error and never redirects — the open-redirect law). OWNER-gated engine-side (the mintApiKey posture; consent is an owner act). Template class (integration config — off the floor)." connectorAuthorization(responseType: String!, clientId: String!, redirectUri: String!, codeChallenge: String!, codeChallengeMethod: String!, state: String, scope: String, resource: String): ConnectorAuthorizationReview! "ONE resource's availability facts over [from, to): the advisory weekly hours + the capacity + the RESERVED bookings overlapping the window. The resource must exist in YOUR org group. The client composes free slots. Requires authentication (template class)." schedulableResourceAvailability(resourceId: ID!, from: String!, to: String!): SchedulableResourceAvailability! "The AT-maintained canned storefront-theme roster: createStorefront/updateStorefront must name a listed key (the refusal NAMES the roster). Unpaginated bounded roster (not a construct list). Requires authentication." cannedStorefrontThemes: [StorefrontTheme!]! "One page of YOUR org group's fiscal receipts. Requires authentication (template class). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared FiscalReceipt roster: `caption` (text) · `status` (enum) · `parentKind` (enum) · `regime` (enum) · `logicalFacilityId` (ref) · `seriesKey` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null). ⚠ `status` carries the ONE artifact literal `issued` — every live row matches (grammar parity, never narrowing)." fiscalReceipts(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): FiscalReceiptPage! "ONE fiscal receipt by id, within your org group. Requires authentication (template class)." fiscalReceipt(id: ID!): FiscalReceipt "The AT-maintained canned fiscal-regime roster: issueFiscalReceipt must name a listed key (the refusal NAMES the roster). Unpaginated bounded roster (not a construct list). Requires authentication." cannedFiscalRegimes: [FiscalRegime!]! "One dashboard's widgets ANSWERED: each canned metric computed at read time, ordinal-ordered. The lanes: bounded status counts (orders_open = open/held/placed · cs_open_cases = cases where work remains · fraud_alerts_open = awaiting first triage) · windowed sales sums PER CURRENCY (sales_today = the UTC calendar day · sales_week = the trailing 7 days; placed/completed orders by creation instant, never cross-currency) · loyalty_signups_30d (members created in the trailing 30 days — a signup is a birth event, status-blind) · inventory_value (Σ on-hand × weighted-average cost per currency; items without a cost basis are excluded) · sell_through_30d · review_average (the published-review aggregate — the average ×100 beside its census) · low_stock_count (the per-organization buy-desk snapshots summed — every ACTIVE organization must have been desk-evaluated, asOf = the oldest evaluation; an unevaluated organization refuses naming it). EVERY answer is honest-or-absent: a lane whose rows exceed the per-lane walk cap (2000), nothing to measure yet, or a sum past the wire's integer ceiling answers available:false with a plain-words reason — never a clipped figure. Group-wide (the construct's own scope). The dashboard must exist in YOUR org group. Requires authentication (template class)." dashboardMetrics(id: ID!): DashboardMetrics! "One construct's archived revision history: the full prior items, cause-stamped, from the revision archive. The target must exist in YOUR tenant (a foreign/unknown target refuses NOT_FOUND); a DOOMED record's history remains readable (the dooming IS history); revisions land moments after each commit (the archive rides the change stream). limit defaults 100, clamps at 200. order defaults oldest (the walkable history); order: newest answers the LATEST rows first, UNPAGINATED (a nextToken with newest refuses) — the last-touch lane's read. Requires authentication." revisions(targetType: String!, targetConstructId: ID!, limit: Int, nextToken: String, order: String): ConstructRevisionPage! "The target's likely-next actions: with a construct id, the record's LIVE status × the registry's realized ops, ranked by the curated per-type×state order; WITHOUT one, the family's BIRTH op (record-creating acts surface as suggestions, never as fixed links). Either way filtered to what YOU may actually perform (capability + descriptors — a suggestion you cannot take is never returned). A given target must exist in YOUR tenant (a foreign/unknown target refuses NOT_FOUND — the revisions gate); a terminal record answers its honest remainder (usually empty). Ranked server-side — render verbatim. Requires authentication." suggestedActions(targetType: String!, targetConstructId: ID): [SuggestedAction!]! "Render verbatim. Requires authentication (user sessions — an api key has no worklist)." needsAttention: [NeedsAttentionEntry!]! "Interpret a WRITTEN request into structured filter conditions for a declared filterable family: the model DRAFTS under a schema constrained to the family's roster, the server RE-VALIDATES every clause exactly as hand-built (the grammar disposes), and reference NAMES resolve in-tenant (ambiguity answers candidates for the picker — no tenant data leaves the platform; the prompt carries only the roster, its vocabularies, and your sentence). Inexpressible parts come back worded in unmappable. NOTHING auto-applies — the answer pre-fills the builder and Apply stays yours. `type` must be a declared filterable family; `text` is one sentence (<= 500 chars). Refuses INTEGRATION/UNAVAILABLE while the interpreter is offline/keyless — build the filter by hand. Requires authentication (user sessions). Every call is cost-metered (at.ai.call.v1)." interpretFilter(type: String!, text: String!): InterpretedFilter! "Run ONE search plan synchronously, as you, inside your tenant: start at a plan-searchable family with optional filter clauses (the FilterInput grammar VERBATIM), hop along KNOWN relationships (outbound follows a reference field of the current family to the family it names; inbound walks a referring family and keeps the rows whose reference names a current match — at most 3 hops, each with its own clauses against ITS family), and answer the LAST step's rows as six-field summaries — newest first (updatedAt desc, id tiebreak), up to `limit` (1..200; absent = 100) — with the EXACT matchCount, the records examined, the elapsed ms, the plan in words, and the estimate the run made before reading anything. THE PLAN GATE refuses BEFORE any read — an unknown family, a field outside its roster, a hop that is not a relationship of the current family — naming the legal words. the budget rule refuses a plan that would examine more than 5000 records (measured KEYS ONLY before the first read), a step that matches more than 1000, or a run past 8 s — no partials in this synchronous lane. Every refusal is VALIDATION/INVALID in the teaching voice. AS YOU: a family you may not list refuses the whole plan before any read; the tenant rides every key. A JSON null on an optional input field reads as absent. Requires authentication." searchPlanRun(plan: SearchPlanInput!): SearchPlanRun! "Draft ONE search plan from plain words: the assistant routes your words onto the plan grammar — the start family, up to 3 hops along KNOWN relationships, each step's conditions — in ONE strict structured call; then each step's conditions pass through the SAME interpreter the filter builder uses (names resolve inside your tenant; every clause re-validated exactly as hand-built); the assembled plan passes THE PLAN GATE before you see it (a refused plan is re-asked ONCE with the gate's own words, then refused VALIDATION/INVALID in the teaching voice). NOTHING runs and nothing is saved: the answer is the plan IN WORDS + the exact JSON document searchPlanRun(plan) / startSearchJob(plan) accept — you decide. `words` is one written ask, 1..500 characters. Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — build the plan by hand. Requires authentication (user sessions). Every call is cost-metered (at.ai.call.v1 — the route call as office.plan_draft, each step as office.filter_interpret)." draftSearchPlan(words: String!): SearchPlanDraft! "Run ONE report synchronously, as you, inside your tenant: a report WRAPS a search plan (the SearchPlanInput grammar VERBATIM — the start, up to 3 hops, the limit; THE PLAN GATE and the budget rule of searchPlanRun apply unchanged: a plan that would examine more than 5000 records (measured KEYS ONLY before the first read), a step over 1000 matches, or a run past 8 s refuses BEFORE partials exist — a plan too large for this lane says so and names the other one: start it as a background report) and says WHAT TO SAY about the LAST step's records — EITHER `columns` (a PROJECTION: 1..24 fields of the terminal family — its declared filter roster plus the header leaves id · sysId · caption · status · createdAt · updatedAt; one row per record, newest first (updatedAt desc, id tiebreak), up to the plan's `limit`; a money column brings its currency column, a reference column brings its `.caption`) OR `groupBy` + `measures` (an AGGREGATE: 1..4 keys — enum, reference, text, flag or bucketed date fields (a date key NEEDS a bucket: day · week · month · quarter · year) — and up to 8 measures over money or number fields (sum · min · max · avg; `count` is ALWAYS the first measure whether named or not); a money measure joins the row's currency to the group implicitly and renders decimals by the currency's exponent, so two currencies are never summed together; at most 1000 distinct groups — past it the run refuses and asks for a coarser bucket or a condition) — never both, never neither. An optional `sort` names an OUTPUT column (`totalMinor.sum`, `createdAt.month`, `count`, …). The answer: the report in words, the terminal family, THE OUTPUT PLAN (`columns` — name + kind; the CSV header in this order), the rows as ONE JSON array text (`rowsJson` — parse it; a row's keys are the column names), rowCount · groupCount (0 for a projection) · the records examined · the pre-read estimate · the elapsed ms, and `captionsOmitted` — the reference families whose `.caption` column was dropped because you may not list them (the id column stands; no refusal). Every refusal is VALIDATION/INVALID in the teaching voice — the legal fields named. 📊 THE REPORT NAMED ONE WAY — exactly one of spec (an ad hoc report) or reportId (a saved Report definition, run as YOU, its spec re-validated now): both or neither refuses VALIDATION/INVALID; an inactive or doomed definition refuses CONFLICT/REF_STATE naming its state. AS YOU: a family you may not list refuses the whole plan before any read; the tenant rides every key. A JSON null on an optional input field reads as absent. Requires authentication." reportRun(spec: ReportSpecInput, reportId: ID): ReportRows! "Draft ONE report definition from plain words: the assistant routes your words onto the plan grammar AND the report shape in ONE strict structured call — the start family, up to 3 hops along KNOWN relationships, each step's conditions, plus what to list (columns) or how to group and total (groupBy + measures) IN WORDS; each step's conditions pass through the SAME interpreter the filter builder uses (names resolve inside your tenant; every clause re-validated exactly as hand-built); the plan passes THE PLAN GATE; then ONE more strict call resolves the worded columns, keys and measures against the LAST family's own roster (a closed list of its reportable field names — nothing outside it can be emitted); the assembled spec passes THE REPORT GATE before you see it (a refused plan re-asks the route ONCE, a refused shape re-asks the resolve ONCE — each with the gate's own words — then VALIDATION/INVALID in the teaching voice). `words` is one written ask, 1..500 characters. Metered office.report_draft (the route + the resolve) and office.filter_interpret per step. Refuses INTEGRATION/UNAVAILABLE while the planner is offline/keyless — build the report by hand. Requires authentication (user sessions only — the interpretFilter class)." draftReport(words: String!): ReportDraft! "Read ONE background search's result set: the matches of the plan's LAST family as six-field summaries — newest first (updatedAt desc, id tiebreak), up to the plan's `limit` — with the EXACT matchCount, the records examined, and `partial` (true when the job halted before finishing — a refused plan, the 300 s clock, or a cancel — the partials it had survive). The result set lives 7 days from the finish (`expiresAt`); afterwards `expired` is true and the matches are gone (the job record stays readable). A job still running answers no matches yet with partial true. AS YOU: the matches are gated by YOUR OWN right to list the plan's last family — refused AUTHZ/FORBIDDEN naming it; a job outside your tenant, or none at all, is NOT_FOUND. Requires authentication." searchJobMatches(id: ID!): SearchJobMatches! "Download ONE finished background export's FILE: a short-lived presigned GET (alive 300 s — `expiresAt`) on the composed file, the name to save it as (`fileName` — --.), and the file's facts off the record (`bytes` · `rowCount` · `format` · `partial` — true when the run halted before the end and the file holds what was written). The file lives 7 days from the finish; afterwards NOT_FOUND worded expired (the record stays readable). YOURS ALONE: only the job's OWNER may download — anyone else refuses AUTHZ/FORBIDDEN — and YOUR OWN right to list the plan's last family is re-checked (refused AUTHZ/FORBIDDEN naming it); a job that is not done (cancelled · expired · failed) refuses CONFLICT/REF_STATE naming its status; a job outside your tenant, or none at all, is NOT_FOUND. Requires authentication (user sessions)." exportJobDownload(id: ID!): ExportJobDownload! "Draft up to count (1..10) candidate questions for ONE course through the assistant, GROUNDED on the play's own words alone — its title, its line, its steps and the operations' guide summaries. Every candidate is parsed one by one through the strict TrainingQuestionDraft schema; the invalid are DROPPED AND COUNTED (dropped). NOTHING is stored — save each kept one through createTrainingQuestion with source drafted. A metered AI read (office.training_draft) on the USER plane; requires the training-manage right. courseKey must be a live play key (VALIDATION otherwise); the assistant unavailable (keyless, a provider fault, an unreadable answer) answers INTEGRATION/UNAVAILABLE — write the questions by hand." draftTrainingQuestions(courseKey: String!, count: Int!): TrainingQuestionDrafts! "YOUR OWN training standing: the active requirements binding one of your roles' templates in this organization, each with dueAt and certified · your progress per play · your courses · your open sittings · your valid certificates. Requires authentication on a USER session." myTraining: MyTraining! "Open ONE sitting whole: the attempt + its drawn questions in the STORED draw's order — a bounded batch by id, never a scan. YOUR OWN by id; another person's needs the org-wide list right (trainingAttempts) — refused AUTHZ/FORBIDDEN naming what it needs; a miss refuses NOT_FOUND/CONSTRUCT. correctIndex and explanation are null while the attempt is open and present once submitted, for EVERY caller; a NON-subject reader's answers and score follow training.score_visibility (2 whole · 1 the answers withheld · 0 the answers and the score withheld). SELF-classified — every principal keeps it." trainingSitting(id: ID!): TrainingSitting! "Ask the tutor ONE question about ONE course (🎓: ONE strict call on the metered AI lane (office.training_tutor) GROUNDED on the course's own words, its ACTIVE question bank (the right answers and explanations the manager authored) and the questions YOU missed on your last practice — the answer (at most 1200 characters) names the steps and questions it rests on (grounds). question is 1..400 characters (VALIDATION otherwise); stepN, when given, is one of the play's steps. At most 30 asks an hour per person (RATE_LIMIT/THROTTLED with retryAfterSeconds — unmetered); a keyless or failing assistant refuses INTEGRATION/UNAVAILABLE — the course's steps are the answer. NOTHING is stored. SELF on the USER plane — every principal keeps it." trainingTutor(courseKey: String!, question: String!, stepN: Int): TrainingTutorAnswer! "Suggest a cleaned-up display name: the model fixes casing, stray whitespace, and obvious typos in YOUR draft — it never invents a different name. The answer arrives already normalized under the name rule (ends trimmed; internal whitespace runs collapsed to one space) and bounded 1..160 like every stored caption. `type` is the record kind word (prompt context only); `text` is the draft name (<= 500 chars). NOTHING auto-applies — the answer pre-fills the rename input. Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — clean the name by hand. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." suggestCaption(type: String!, text: String!): SuggestedCaption! "Suggest a FREE code for a record from its name. DETERMINISTIC, no AI call, nothing metered: the name's words uppercase and join with hyphens (bounded 24 chars; diacritics fold), numbered -2, -3, … when taken. For families whose codes are unique (Organization — unique across the whole platform) every candidate is checked against the SAME reservation the save enforces, so the answer is free AT ANSWER TIME — a race can still take it before you save, and the save then refuses honestly (CONFLICT/IDENTITY_TAKEN, nothing changes). Families whose codes are freely chosen answer the derivation directly. `type` must name a code-bearing record family (the declared roster — an unknown family refuses VALIDATION/INVALID); `text` is the name to derive from (<= 500 chars; must contain a letter or digit). NOTHING auto-applies — the answer pre-fills the code input. Requires authentication (user sessions)." suggestCode(type: String!, text: String!): SuggestedCode! "Suggest a short change-log reason for the edit you are about to save: the model drafts ONE plain sentence (two at most) from the change summary the office composed — what changed, and where the summary makes it obvious, why. It never invents facts beyond the summary. The answer arrives trimmed and bounded 1..256 like every stored cause reason. `type` is the record kind word (prompt context only); `text` is the change summary (<= 500 chars). NOTHING auto-applies — the answer pre-fills the reason input. Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — write the reason by hand. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." suggestReason(type: String!, text: String!): SuggestedReason! "Ask AI to review one record for data-quality issues: the model reads the record CONTENT YOU SENT — the same label/value lines the detail page shows (the server reads no tenant data of its own) — and answers a short plain-text review: 2..6 issue lines naming fields that look incomplete, inconsistent, placeholder-like, or suspicious, or exactly 'No issues found.'. READ-ONLY ADVICE — nothing changes on the record. The answer arrives trimmed and bounded 1..2000. `type` is the record kind word (prompt context only); `text` is the record content (<= 4000 chars). Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — review the record by eye. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." reviewRecord(type: String!, text: String!): RecordReview! "Ask AI to draft values for the EMPTY inputs of ONE wizard/form step AND check the answered ones: the model reads what YOU SENT — FILLED (the step's answered label: value lines the merchant already sees) and WANT (one line per empty field: name — label (kind): help; EMPTY = verify-only) — the server reads no tenant data of its own — and answers suggestions ONLY for WANT fields it can predict from FILLED (unpredictable fields are skipped honestly; an empty list is a legal answer) plus `advice`: a short verification of FILLED (formats · consistency · real-world plausibility — an address's parts must agree; '' = nothing to flag). DRAFTS ONLY — nothing applies or corrects automatically. `type` is the record kind word (prompt context only, 1..64); `step` the page word (1..120); `filled` 1..4000 chars; `want` 0..2000 chars; `materialIds` names ≤4 of YOUR OWN confirmed wizard materials on the SAME type word — their stored extractions compose into the model's context (raw content is never re-read; a foreign/mismatched id refuses NOT_FOUND). Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — fill by hand. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." suggestFormFill(type: String!, step: String!, filled: String!, want: String!, materialIds: [ID!]): FormFillSuggestion! "Ask AI to explain where you are on ONE wizard/form step: the model reads what YOU SENT — FILLED (the step's answered label: value lines; EMPTY is lawful: the first-page press) and WANT (one line per empty field) — the server reads no tenant data of its own — and narrates what this step is doing, what you have provided, and what is still needed and WHY each missing piece matters. GUIDANCE ONLY — nothing applies, fills, or changes (the fill assist is suggestFormFill). `type` is the record kind word (prompt context only, 1..64); `step` the page word (1..120); `filled` 0..4000 chars; `want` 0..2000 chars; `materialIds` composes YOUR OWN confirmed materials' stored extractions exactly as on suggestFormFill (≤4, same type word, never a raw re-read). Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — the page's static guide words still stand. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." explainWizardStep(type: String!, step: String!, filled: String!, want: String!, materialIds: [ID!]): StepExplanation! "Ask AI to draft ONE internal note: with an EMPTY draft the model WRITES a note from the CONTEXT YOU SENT (the visible thread + the record word — the server reads no tenant data of its own); with a PRESENT draft it CLEANS/enhances YOUR OWN words (same facts and intent, never new claims). The answer PRE-FILLS the composer — NOTHING posts automatically. Trimmed and bounded 1..4096 (what cannot post is never suggested). `type` is the record kind word; `context` <= 4000 chars; `draft` <= 4096 chars (empty = the write-me face). Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — write the note by hand. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." suggestNote(type: String!, context: String!, draft: String!): SuggestedNote! "Ask AI to summarize one record's note thread: the model reads the THREAD YOU SENT (one line per note — the server reads no tenant data of its own) and answers a short plain-text synopsis: what the thread is about, what was decided, what still hangs — 2..6 lines. A synopsis is not an issues-review (that is reviewRecord). READ-ONLY — nothing changes. Trimmed and bounded 1..2000. `type` is the record kind word; `text` is the thread (<= 4000 chars). Refuses INTEGRATION/UNAVAILABLE while the assistant is offline/keyless. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." summarizeThread(type: String!, text: String!): ThreadSummary! "YOUR group's AI usage by UTC day: composed off the daily rollup rows the meter grows with EVERY metered call (calls · tokens · nano-exact spend + the per-surface split), ≤ 92 bounded point-reads — never a scan. SELF-group BY CONSTRUCTION (no target arg exists — the tokenEntries stance); days defaults 30, clamps 1..92; only days WITH usage answer (an empty window is the honest answer). costUsd values are decimal strings (the money-string law). Requires authentication." aiUsage(days: Int): AiUsageWindow! "YOUR group's fired AI-watch flags by UTC day. Actor captions resolve at read (a user actor names itself; a session actor answers 'other'). SELF-group BY CONSTRUCTION (no target arg exists — the aiUsage stance). Requires authentication." aiFlags(days: Int): AiFlagWindow! "YOUR group's AI calls WITH the words, NEWEST first (🧾 — THE AI LEDGER + the echo rule): the backwards month walk from this month to the 13-month floor (the rows live 13 months hot; the event lake keeps them forever). limit: 1..200, default 50. nextToken: the prior page's cursor VERBATIM (opaque, group-bound — a foreign or garbled token refuses VALIDATION/INVALID). month: ONE YYYY-MM bucket — the walk stays in it (nextToken null when it is exhausted). surface: one of the at.ai.call.v1 roster (e.g. office.report_draft) — a filter in the walk (a rare surface over a dense month may answer a SHORT page with a cursor: keep walking). day (YYYY-MM-DD, UTC) pins ONE calendar day of ONE bucket — the sk prefix, a bounded key read; with month they must agree. A16_BILLING by override; excluded from the consult tools and the read-only integration key." aiCalls(limit: Int, nextToken: String, month: String, surface: String, day: String): AiCallPage! "Read ONE of YOUR wizard drafts: its status, the sheet page by page once ready (each value with its source and confidence), the assistant's questions and advice, what it said it understood, and failReason when it failed. YOURS ALONE: another person's draft, a draft outside your tenant, or none at all is NOT_FOUND. Requires authentication (user sessions)." fillDraft(id: ID!): FillDraft! "YOUR wizard drafts, NEWEST first: status filters by drafting | ready | failed (abandoned drafts drop from the list and stay readable one at a time); limit 1..200 (default 50); nextToken the prior page's cursor VERBATIM (opaque, tenant-bound). A page may be SHORT (the owner/status filter rides per id page) — walk until nextToken is null. Requires authentication (user sessions)." fillDrafts(status: FillDraftStatus, limit: Int, nextToken: String): FillDraftPage! "The conversation on ONE of YOUR wizard drafts, OLDEST first: what you said and what the assistant answered, turn by turn (a failed assistant turn says why; sheetRevised says the sheet changed under a reply). YOURS ALONE: another person's draft, a draft outside your tenant, or none at all is NOT_FOUND. limit 1..200 (default 50); nextToken the prior page's cursor VERBATIM (opaque, bound to this draft). Requires authentication (user sessions)." fillDraftTurns(id: ID!, limit: Int, nextToken: String): FillDraftTurnPage! "YOUR group's metered consumption by UTC day, in KERNELS: composed off the daily rollup rows the billing RATER grows with every rated batch, ≤ 92 bounded point-reads — never a scan. ONE lane per call: no drill arg = the whole group (TOTAL); userId = that user's lane; sessionId = that session's lane (userId AND sessionId together refuse VALIDATION — one grain at a time). SELF-group BY CONSTRUCTION (the tokenEntries stance); days defaults 30, clamps 1..92; only days WITH usage answer. Events predating the attribution stamps roll into the group lane only — a user/session window over old history answers honestly empty. Requires authentication." usageReport(days: Int, userId: ID, sessionId: ID): UsageReportWindow! "ONE page of YOUR group's sessions, NEWEST FIRST: every sign-in/exchange mints one; terminals stay listed (an ended sitting still has usage to drill — no-delete); doomed drops per page. `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token refuses VALIDATION/INVALID). Walk until `nextToken` is null (doomed drop per page — a page may hold fewer than `limit`). SELF-group BY CONSTRUCTION (no target arg exists). Requires authentication." sessions(limit: Int, nextToken: String): SessionPage! "Ask the page-aware assistant ONE written question about using AlmondTill/G3N: the answer grounds on the SAME guide corpus the Guide tab shows, WHERE you are and WHAT you look at, YOUR SESSION'S prior exchanges (the context follows your login session across pages — older exchanges condense into a rolling memory; the reply's contextTurns/contextTurnsMax/contextFolded carry the honest meter), and — when your role permits — LIVE READS of your own records requested by the assistant mid-answer (every read runs under YOUR permissions exactly as if you ran it; a read the assistant may run in the background is one you could run yourself). A READ-ONLY advisor: it can look things up, it never changes anything. Answers may link real pages from the app's own route directory. `question` is one written ask (<= 500 chars). Per-user hourly allowance (RATE_LIMIT/THROTTLED when spent). Refuses VALIDATION/INVALID at the full context (clear it and re-ask) and INTEGRATION/UNAVAILABLE while the assistant is offline/keyless — the Guide tab stands. Requires authentication (user sessions). Every made call is cost-metered (at.ai.call.v1)." assistantAsk(context: AssistantContextInput!, question: String!): AssistantAnswer! "One page of a Consultation's transcript, OLDEST FIRST. The consultation must be yours-in-tenant (a missing/foreign head refuses NOT_FOUND). Requires authentication. read." consultationTurns(id: ID!, limit: Int, nextToken: String): ConsultationTurnPage! "The LIVE tax-jurisdiction country roster: the ISO 3166-1 alpha-2 codes of every seeded canonical country tree, from the ONE self-maintaining registry row the country-mint path grows — the office dropdown can never drift from the live trees again. Sorted; an unseeded estate answers the honest empty list. Requires authentication." taxJurisdictionCountries: [String!]! "Doomed branches drop per page; an unknown or childless parentId answers the honest empty page. STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TaxJurisdiction roster: `caption` (text) · `level` (enum: country, state_province, county, city, special_district) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the parent's WHOLE children set server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE parent + filter + sort that minted it — replaying it elsewhere refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null). SHARED canonical data — no tenant scoping. Requires authentication." taxJurisdictionChildren(parentId: ID!, filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TaxJurisdictionPage! "ONE page of a Category's DIRECT children: the merchandise tree browses level by level, one bounded tree-children page per call. Doomed branches drop per page; a parentId outside YOUR tenant — or unknown, or childless — answers the honest empty page. STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Category roster: `caption` (text) · `status` (enum) · `treeParent` (ref) · `merchandiseDivisionId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the parent's WHOLE children set server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE parent + filter + sort that minted it — replaying it elsewhere refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null). Requires authentication." categoryChildren(parentId: ID!, filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CategoryPage! "Resolve a postal code to the tax jurisdiction(s) that apply there: ONE bounded read; the primary designation leads, straddling alternates follow. An unknown code — or a country without postal content — answers the honest empty resolution (primary null, alternates). Malformed input refuses VALIDATION/INVALID before any read. SHARED canonical data — no tenant scoping. Requires authentication." resolveTaxJurisdictionByPostal(countryCode: String!, postal: String!): TaxJurisdictionPostalResolution! "The calling principal's OWN Account identity. USER-plane only (api/device/consumer sessions have no acting account face). Requires authentication." myAccount: MyAccount! "Your OWN organization group. SELF BY CONSTRUCTION (no target arg exists — the principal's rootId). Projects the identity + governance facts ONLY (the referral provenance and the standings are NOT projected). Requires authentication (the staff planes — user, api, and collaborator sessions)." myOrganizationGroup: OrganizationGroup! "The calling account's OWN identity-verification standing. required derives LIVE from the structural owners arrays; a stale non-terminal standing reconciles against Stripe on read (lost webhooks self-cure). Requires authentication." myIdentityVerification: IdentityVerificationReport! "ONE of your own app-private values at this organization. ABSENT = null, never an error — absence is a legal preference state. Requires authentication." myAppData(app: String!, name: String!): MyAppDataEntry "The names + stamps of your saved values for one app, values EXCLUDED. SELF-scoped BY CONSTRUCTION. Requires authentication." listMyAppData(app: String!): [MyAppDataEntrySynopsis!]! "The AT-maintained preset peripheral-model roster: every model names its peripheralType + supported connections; createDevicePeripheral must cohere with a row. Unpaginated bounded roster (not a construct list). Requires authentication." cannedPeripheralModels: [PeripheralModel!]! "How many records point at ONE record, per referencing family and field: the doors derive from the declared filter rosters (every family whose ref field names `type`), and EACH COUNT IS THAT DOOR'S OWN FILTERED LISTING'S matchCount — the number the door shows when opened, by construction (the doomed-drop and the tenant fence are the listing's). A family whose listing the caller's roles refuse is OMITTED (never 0). BOUNDED: the call hydrates at most 5000 rows across every door family — the families are measured keys-only first and walk smallest-first; a family that does not fit answers count null and `partial: true` rides the answer (the face renders the glyph alone). `type` must be a known construct type (VALIDATION/INVALID names it); `id` is any id — a foreign or unknown id counts zero everywhere (no existence read). Requires authentication." relationshipCounts(type: String!, id: ID!): RelationshipCounts! "A PhysicalFacilityLocation by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." physicalFacilityLocation(id: ID!): PhysicalFacilityLocation "The caller's org-group family's ACTIVE LISTING of PhysicalFacilityLocations — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared PhysicalFacilityLocation roster: `caption` (text) · `taxJurisdictionId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." physicalFacilityLocations(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): PhysicalFacilityLocationPage! "A PhysicalFacility by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." physicalFacility(id: ID!): PhysicalFacility "The caller's org-group family's ACTIVE LISTING of PhysicalFacilities — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared PhysicalFacility roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `physicalFacilityLocationId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." physicalFacilities(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): PhysicalFacilityPage! "A LogicalFacility by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." logicalFacility(id: ID!): LogicalFacility "The caller's org-group family's ACTIVE LISTING of LogicalFacilities — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared LogicalFacility roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `organizationId` (ref) · `classification` (enum) · `geographicDivisionId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." logicalFacilities(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): LogicalFacilityPage! "A Zone by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." zone(id: ID!): Zone "The caller's org-group family's ACTIVE LISTING of Zones — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Zone roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `coordinates` (text) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." zones(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ZonePage! "A Bin by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." bin(id: ID!): Bin "The caller's org-group family's ACTIVE LISTING of Bins — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Bin roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `coordinates` (text) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." bins(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): BinPage! "A Role by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." role(id: ID!): Role "The caller's org-group family's ACTIVE LISTING of Roles — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Role roster: `caption` (text) · `status` (enum) · `authorityTier` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." roles(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): RolePage! "A User by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." user(id: ID!): User "The caller's org-group family's ACTIVE LISTING of Users — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared User roster: `caption` (text) · `status` (enum) · `accountId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." users(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): UserPage! "A Brand by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." brand(id: ID!): Brand "The caller's org-group family's ACTIVE LISTING of Brands — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Brand roster: `caption` (text) · `status` (enum) · `code` (text) · `description` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." brands(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): BrandPage! "A Season by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." season(id: ID!): Season "The caller's org-group family's ACTIVE LISTING of Seasons — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Season roster: `caption` (text) · `status` (enum) · `code` (text) · `startAt` (date) · `endAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." seasons(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SeasonPage! "A Tag by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." tag(id: ID!): Tag "The caller's org-group family's ACTIVE LISTING of Tags — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Tag roster: `caption` (text) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." tags(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TagPage! "A Characteristic by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." characteristic(id: ID!): Characteristic "The caller's org-group family's ACTIVE LISTING of Characteristics — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Characteristic roster: `caption` (text) · `valueType` (enum) · `unit` (text) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." characteristics(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CharacteristicPage! "A CustomUom by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." customUom(id: ID!): CustomUom "The caller's org-group family's ACTIVE LISTING of CustomUoms — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared CustomUom roster: `caption` (text) · `status` (enum) · `dimensionClass` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." customUoms(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CustomUomPage! "A Manufacturer by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." manufacturer(id: ID!): Manufacturer "The caller's org-group family's ACTIVE LISTING of Manufacturers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Manufacturer roster: `caption` (text) · `status` (enum) · `code` (text) · `origin` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." manufacturers(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ManufacturerPage! "A Vendor by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." vendor(id: ID!): Vendor "The caller's org-group family's ACTIVE LISTING of Vendors — doomed records DROP from listings." vendors: [Vendor!]! "A Category by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." category(id: ID!): Category "The caller's org-group family's ACTIVE LISTING of Categories — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Category roster: `caption` (text) · `status` (enum) · `treeParent` (ref) · `merchandiseDivisionId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." categories(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CategoryPage! "A Division by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." division(id: ID!): Division "The caller's org-group family's ACTIVE LISTING of Divisions — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Division roster: `caption` (text) · `status` (enum) · `divisionType` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." divisions(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DivisionPage! "A OptionGroup by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." optionGroup(id: ID!): OptionGroup "The caller's org-group family's ACTIVE LISTING of OptionGroups — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OptionGroup roster: `caption` (text) · `status` (enum) · `optionGroupType` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." optionGroups(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OptionGroupPage! "A OptionValue by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." optionValue(id: ID!): OptionValue "The caller's org-group family's ACTIVE LISTING of OptionValues — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OptionValue roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." optionValues(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OptionValuePage! "A Decoration by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." decoration(id: ID!): Decoration "The caller's org-group family's ACTIVE LISTING of Decorations — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Decoration roster: `caption` (text) · `status` (enum) · `purpose` (enum) · `locale` (text) · `text` (text) · `attachedToType` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." decorations(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DecorationPage! "A OrgManufacturer by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgManufacturer(id: ID!): OrgManufacturer "The caller's org-group family's ACTIVE LISTING of OrgManufacturers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OrgManufacturer roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `manufacturerId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orgManufacturers(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrgManufacturerPage! "A OrgBrand by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgBrand(id: ID!): OrgBrand "The caller's org-group family's ACTIVE LISTING of OrgBrands — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OrgBrand roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `brandId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orgBrands(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrgBrandPage! "A OrgSeason by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgSeason(id: ID!): OrgSeason "The caller's org-group family's ACTIVE LISTING of OrgSeasons — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OrgSeason roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `seasonId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orgSeasons(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrgSeasonPage! "A OrgDivision by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgDivision(id: ID!): OrgDivision "The caller's org-group family's ACTIVE LISTING of OrgDivisions — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OrgDivision roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `divisionId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orgDivisions(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrgDivisionPage! "A OrgVendor by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgVendor(id: ID!): OrgVendor "The caller's org-group family's ACTIVE LISTING of OrgVendors — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OrgVendor roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `vendorId` (ref) · `accountNumber` (text) · `purchasingCurrency` (text) · `paymentTerms` (enum) · `incotermCode` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orgVendors(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrgVendorPage! "A Style by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." style(id: ID!): Style "The caller's org-group family's ACTIVE LISTING of Styles — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Style roster: `caption` (text) · `status` (enum) · `styleType` (enum) · `brandId` (ref) · `taxCategory` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." styles(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): StylePage! "A Product by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." product(id: ID!): Product "The caller's org-group family's ACTIVE LISTING of Products — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Product roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." products(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ProductPage! "A Variant by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." variant(id: ID!): Variant "The caller's org-group family's ACTIVE LISTING of Variants — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Variant roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `stockUomKind` (enum) · `stockUomRef` (text) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." variants(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): VariantPage! "A OrgStyle by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgStyle(id: ID!): OrgStyle "The caller's org-group family's ACTIVE LISTING of OrgStyles — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared OrgStyle roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `styleId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orgStyles(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrgStylePage! "A ProductRelation by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." productRelation(id: ID!): ProductRelation "The caller's org-group family's ACTIVE LISTING of ProductRelations — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared ProductRelation roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `targetProductId` (ref) · `relationType` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." productRelations(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ProductRelationPage! "A Collection by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." collection(id: ID!): Collection "The caller's org-group family's ACTIVE LISTING of Collections — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Collection roster: `caption` (text) · `status` (enum) · `collectionType` (enum) · `sortMode` (enum) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." collections(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CollectionPage! "A CollectionMember by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." collectionMember(id: ID!): CollectionMember "The caller's org-group family's ACTIVE LISTING of CollectionMembers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared CollectionMember roster: `caption` (text) · `parentId` (ref) · `productId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." collectionMembers(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CollectionMemberPage! "A VariantComponent by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." variantComponent(id: ID!): VariantComponent "The caller's org-group family's ACTIVE LISTING of VariantComponents — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared VariantComponent roster: `caption` (text) · `parentId` (ref) · `componentVariantId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." variantComponents(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): VariantComponentPage! "A InventoryItem by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." inventoryItem(id: ID!): InventoryItem "The caller's org-group family's ACTIVE LISTING of InventoryItems — doomed records DROP from listings." inventoryItems: [InventoryItem!]! "A SalePrice by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." salePrice(id: ID!): SalePrice "The caller's org-group family's ACTIVE LISTING of SalePrices — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared SalePrice roster: `caption` (text) · `parentId` (ref) · `startAt` (date) · `endAt` (date) · `markdownPlanId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." salePrices(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SalePricePage! "A Transfer by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." transfer(id: ID!): Transfer "The caller's org-group family's ACTIVE LISTING of Transfers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Transfer roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `destinationLogicalFacilityId` (ref) · `weight` (enum) · `sourceOrganizationId` (ref) · `destinationOrganizationId` (ref) · `expectedArrivalAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." transfers(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TransferPage! "A TransferRequest by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." transferRequest(id: ID!): TransferRequest "The caller's org-group family's ACTIVE LISTING of TransferRequests — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TransferRequest roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `requestingOrganizationId` (ref) · `targetLogicalFacilityId` (ref) · `neededBy` (date) · `priority` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." transferRequests(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TransferRequestPage! "A Count by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." count(id: ID!): Count "The caller's org-group family's ACTIVE LISTING of Counts — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Count roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `organizationId` (ref) · `countType` (enum) · `recountOfCountId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." counts(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CountPage! "A Contact by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." contact(id: ID!): Contact "The caller's org-group family's ACTIVE LISTING of Contacts — doomed records DROP from listings." contacts: [Contact!]! "A ContactAssignment by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." contactAssignment(id: ID!): ContactAssignment "The caller's org-group family's ACTIVE LISTING of ContactAssignments — doomed records DROP from listings." contactAssignments: [ContactAssignment!]! "A WarrantyTerms by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." warrantyTerms(id: ID!): WarrantyTerms "The caller's org-group family's ACTIVE LISTING of WarrantyTermsList — doomed records DROP from listings." warrantyTermsList: [WarrantyTerms!]! "A Warranty by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." warranty(id: ID!): Warranty "The caller's org-group family's ACTIVE LISTING of Warranties — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Warranty roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `organizationId` (ref) · `variantId` (ref) · `productId` (ref) · `warrantyTermsId` (ref) · `consumerId` (ref) · `caseId` (ref) · `provider` (enum) · `serialNumber` (text) · `startsAt` (date) · `expiresAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." warranties(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): WarrantyPage! "A OrgVendorItem by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgVendorItem(id: ID!): OrgVendorItem "The caller's org-group family's ACTIVE LISTING of OrgVendorItems — doomed records DROP from listings." orgVendorItems: [OrgVendorItem!]! "A PurchaseOrder by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." purchaseOrder(id: ID!): PurchaseOrder "The caller's org-group family's ACTIVE LISTING of PurchaseOrders — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared PurchaseOrder roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `orgVendorId` (ref) · `currency` (text) · `vendorReference` (text) · `notes` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." purchaseOrders(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): PurchaseOrderPage! "A Receipt by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." receipt(id: ID!): Receipt "The caller's org-group family's ACTIVE LISTING of Receipts — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Receipt roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `logicalFacilityId` (ref) · `organizationId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." receipts(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ReceiptPage! "A Rtv by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." rtv(id: ID!): Rtv "The caller's org-group family's ACTIVE LISTING of Rtvs — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Rtv roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `purchaseOrderId` (ref) · `shipFromLogicalFacilityId` (ref) · `organizationId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." rtvs(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): RtvPage! "A VendorInvoice by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." vendorInvoice(id: ID!): VendorInvoice "The caller's org-group family's ACTIVE LISTING of VendorInvoices — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared VendorInvoice roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `invoiceOrgVendorId` (ref) · `invoiceNumber` (text) · `invoiceDate` (date) · `notes` (text) · `matchStatus` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." vendorInvoices(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): VendorInvoicePage! "A PurchasePack by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." purchasePack(id: ID!): PurchasePack "The caller's org-group family's ACTIVE LISTING of PurchasePacks — doomed records DROP from listings." purchasePacks: [PurchasePack!]! "A ReplenishmentConfig by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." replenishmentConfig(id: ID!): ReplenishmentConfig "The caller's org-group family's ACTIVE LISTING of ReplenishmentConfigs — doomed records DROP from listings." replenishmentConfigs: [ReplenishmentConfig!]! "A TransferLane by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." transferLane(id: ID!): TransferLane "The caller's org-group family's ACTIVE LISTING of TransferLanes — doomed records DROP from listings." transferLanes: [TransferLane!]! "A TaxJurisdiction by id — SHARED canonical data: AT builds and maintains it; every authenticated principal reads it (NO tenant binding — cross-tenant reading is the point); the wire is READ-ONLY (writes are platform-channel). A missing id reads as null." taxJurisdiction(id: ID!): TaxJurisdiction "countryCode: ISO 3166-1 alpha-2 (uppercase) — resolves ONE country tree via the GLOBAL uniqueness marker (an unseeded country reads as an empty page). ABSENT = the whole canonical family, country by country in ascending code order. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim (malformed/foreign → VALIDATION/INVALID). Doomed records DROP per page — walk until `nextToken` is null. STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TaxJurisdiction roster: `caption` (text) · `level` (enum) · `country` (country) · `postal` (postal) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates its whole SCOPE server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE scope + filter + sort that minted it — replaying it elsewhere refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." taxJurisdictions(countryCode: String, filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TaxJurisdictionPage! "A TaxRate by id — SHARED canonical data: AT builds and maintains it; every authenticated principal reads it (NO tenant binding — cross-tenant reading is the point); the wire is READ-ONLY (writes are platform-channel). A missing id reads as null." taxRate(id: ID!): TaxRate "PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim (malformed/foreign → VALIDATION/INVALID). Doomed records DROP per page — walk until `nextToken` is null. STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TaxRate roster: `caption` (text) · `category` (enum) · `treatment` (enum) · `startAt` (date) · `endAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). ⚠ The anchor COMPOSES with the structured `filter`/`sort` — a filtered/sorted read evaluates the ANCHORED scope server-side, returns the EXACT `matchCount` for that scope, and its `nextToken` binds to THE ONE anchor + filter + sort that minted it — replaying it under a different anchor or filter/sort refuses. Absent both, the unfiltered anchored lane is unchanged (`matchCount` null)." taxRates(jurisdictionId: ID!, filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TaxRatePage! "A TaxRegistration by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." taxRegistration(id: ID!): TaxRegistration "The caller's org-group family's ACTIVE LISTING of TaxRegistrations — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TaxRegistration roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `jurisdictionId` (ref) · `registrationNumber` (text) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." taxRegistrations(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TaxRegistrationPage! "A ExemptionCertificate by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." exemptionCertificate(id: ID!): ExemptionCertificate "The caller's org-group family's ACTIVE LISTING of ExemptionCertificates — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared ExemptionCertificate roster: `caption` (text) · `code` (text) · `certType` (enum) · `certificateNumber` (text) · `holderName` (text) · `expiresAt` (date) · `orgCustomerId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." exemptionCertificates(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ExemptionCertificatePage! "A Order by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." order(id: ID!): Order "The caller's org-group family's ACTIVE LISTING of Orders — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Order roster: `caption` (text) · `status` (enum) · `organizationId` (ref) · `channel` (enum) · `orderType` (enum) · `currency` (text) · `logicalFacilityId` (ref) · `paymentState` (enum) · `fulfillmentState` (enum) · `recognitionState` (enum) · `taxJurisdictionId` (ref) · `validUntil` (date) · `termEndsAt` (date) · `subtotalMinor` (money) · `discountTotalMinor` (money) · `taxTotalMinor` (money) · `totalMinor` (money) · `tenderedNetMinor` (money) · `tipTotalMinor` (money) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." orders(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): OrderPage! "A Invoice by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." invoice(id: ID!): Invoice "The caller's org-group family's ACTIVE LISTING of Invoices — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Invoice roster: `caption` (text) · `status` (enum) · `orderId` (ref) · `organizationId` (ref) · `currency` (text) · `taxMode` (enum) · `taxJurisdictionId` (ref) · `paymentState` (enum) · `fulfillmentState` (enum) · `recognitionState` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." invoices(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): InvoicePage! "A CreditNote by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." creditNote(id: ID!): CreditNote "The caller's org-group family's ACTIVE LISTING of CreditNotes — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared CreditNote roster: `caption` (text) · `status` (enum) · `invoiceId` (ref) · `orderId` (ref) · `organizationId` (ref) · `currency` (text) · `reason` (text) · `settlementState` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." creditNotes(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CreditNotePage! "A DebitNote by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." debitNote(id: ID!): DebitNote "The caller's org-group family's ACTIVE LISTING of DebitNotes — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared DebitNote roster: `caption` (text) · `status` (enum) · `invoiceId` (ref) · `orderId` (ref) · `organizationId` (ref) · `currency` (text) · `reason` (text) · `settlementState` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." debitNotes(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DebitNotePage! "A Saga by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." saga(id: ID!): Saga "The caller's org-group family's ACTIVE LISTING of Sagas — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." sagas(limit: Int, nextToken: String): SagaPage! "A Return by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." return(id: ID!): Return "The caller's org-group family's ACTIVE LISTING of Returns — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Return roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `orderId` (ref) · `invoiceId` (ref) · `organizationId` (ref) · `currency` (text) · `refundTotalMinor` (money) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." returns(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ReturnPage! "A Register by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." register(id: ID!): Register "The caller's org-group family's ACTIVE LISTING of Registers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Register roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." registers(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): RegisterPage! "A TillSession by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." tillSession(id: ID!): TillSession "The caller's org-group family's ACTIVE LISTING of TillSessions — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TillSession roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `openedBy` (ref) · `closedAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." tillSessions(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TillSessionPage! "A ApprovalRequest by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." approvalRequest(id: ID!): ApprovalRequest "The caller's org-group family's ACTIVE LISTING of ApprovalRequests — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." approvalRequests(limit: Int, nextToken: String): ApprovalRequestPage! "A FxRate by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." fxRate(id: ID!): FxRate "The caller's org-group family's ACTIVE LISTING of FxRates — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared FxRate roster: `caption` (text) · `level` (enum) · `fromCurrency` (text) · `toCurrency` (text) · `mode` (enum) · `startAt` (date) · `endAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." fxRates(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): FxRatePage! "A Fulfillment by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." fulfillment(id: ID!): Fulfillment "The caller's org-group family's ACTIVE LISTING of Fulfillments — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Fulfillment roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `orderId` (ref) · `organizationId` (ref) · `method` (enum) · `carrierName` (text) · `packedAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." fulfillments(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): FulfillmentPage! "A Payment by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." payment(id: ID!): Payment "The caller's org-group family's ACTIVE LISTING of Payments — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Payment roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `organizationId` (ref) · `currency` (text) · `amountMinor` (money) · `tipMinor` (money) · `brand` (text) · `last4` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." payments(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): PaymentPage! "A Refund by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." refund(id: ID!): Refund "The caller's org-group family's ACTIVE LISTING of Refunds — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Refund roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `orderId` (ref) · `returnId` (ref) · `organizationId` (ref) · `currency` (text) · `amountMinor` (money) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." refunds(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): RefundPage! "A Dispute by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." dispute(id: ID!): Dispute "The caller's org-group family's ACTIVE LISTING of Disputes — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Dispute roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `orderId` (ref) · `organizationId` (ref) · `currency` (text) · `amountMinor` (money) · `reason` (text) · `evidenceDueBy` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." disputes(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DisputePage! "A Promotion by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." promotion(id: ID!): Promotion "The caller's org-group family's ACTIVE LISTING of Promotions — doomed records DROP from listings." promotions: [Promotion!]! "A Coupon by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." coupon(id: ID!): Coupon "The caller's org-group family's ACTIVE LISTING of Coupons — doomed records DROP from listings." coupons: [Coupon!]! "A StoredValueInstrument by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." storedValueInstrument(id: ID!): StoredValueInstrument "The caller's org-group family's ACTIVE LISTING of StoredValueInstruments — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared StoredValueInstrument roster: `caption` (text) · `status` (enum) · `code` (text) · `instrumentType` (enum) · `currency` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." storedValueInstruments(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): StoredValueInstrumentPage! "A LoyaltyProgram by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." loyaltyProgram(id: ID!): LoyaltyProgram "The caller's org-group family's ACTIVE LISTING of LoyaltyPrograms — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." loyaltyPrograms(limit: Int, nextToken: String): LoyaltyProgramPage! "A LoyaltyMember by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." loyaltyMember(id: ID!): LoyaltyMember "The caller's org-group family's ACTIVE LISTING of LoyaltyMembers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). FILTERS: `programId` — Only members of THIS program (the header parentId). `status` — Only members in THIS FSM status (active|inactive — doomed never lists). `email` — Only members whose NORMALIZED identity email equals this value (normalized server-side — the POS lookup lane)." loyaltyMembers(programId: ID, status: String, email: String, limit: Int, nextToken: String): LoyaltyMemberPage! "A CustomerPriceGroup by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." customerPriceGroup(id: ID!): CustomerPriceGroup "The caller's org-group family's ACTIVE LISTING of CustomerPriceGroups — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared CustomerPriceGroup roster: `caption` (text) · `status` (enum) · `priceListId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." customerPriceGroups(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CustomerPriceGroupPage! "A MarkdownPlan by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." markdownPlan(id: ID!): MarkdownPlan "The caller's org-group family's ACTIVE LISTING of MarkdownPlans — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." markdownPlans(limit: Int, nextToken: String): MarkdownPlanPage! "A CommissionConfig by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." commissionConfig(id: ID!): CommissionConfig "The caller's org-group family's ACTIVE LISTING of CommissionConfigs — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared CommissionConfig roster: `caption` (text) · `status` (enum) · `agentRoleId` (ref) · `agentUserId` (ref) · `divisionId` (ref) · `categoryId` (ref) · `styleId` (ref) · `organizationId` (ref) · `logicalFacilityId` (ref) · `channel` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." commissionConfigs(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): CommissionConfigPage! "A Affiliate by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." affiliate(id: ID!): Affiliate "The caller's org-group family's ACTIVE LISTING of Affiliates — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Affiliate roster: `caption` (text) · `status` (enum) · `consumerId` (ref) · `handle` (text) · `bio` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." affiliates(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): AffiliatePage! "A CorporateCustomer by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." corporateCustomer(id: ID!): CorporateCustomer "The caller's org-group family's ACTIVE LISTING of CorporateCustomers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." corporateCustomers(limit: Int, nextToken: String): CorporateCustomerPage! "A OrgCustomer by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgCustomer(id: ID!): OrgCustomer "The caller's org-group family's ACTIVE LISTING of OrgCustomers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." orgCustomers(limit: Int, nextToken: String): OrgCustomerPage! "A PriceList by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." priceList(id: ID!): PriceList "The caller's org-group family's ACTIVE LISTING of PriceLists — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared PriceList roster: `caption` (text) · `status` (enum) · `startAt` (date) · `endAt` (date) · `orgCustomerId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." priceLists(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): PriceListPage! "A PriceListEntry by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." priceListEntry(id: ID!): PriceListEntry "The caller's org-group family's ACTIVE LISTING of PriceListEntries — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). THE ANCHOR (REQUIRED — it scopes EVERY lane; the walk never leaves it): `priceListId` — THE list anchor (REQUIRED — the taxRates(jurisdictionId) class): only entries of THIS PriceList (the header parentId); tenant-scoped server-side. STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared PriceListEntry roster: `caption` (text) · `startAt` (date) · `endAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). ⚠ The anchor COMPOSES with the structured `filter`/`sort` — a filtered/sorted read evaluates the ANCHORED scope server-side, returns the EXACT `matchCount` for that scope, and its `nextToken` binds to THE ONE anchor + filter + sort that minted it — replaying it under a different anchor or filter/sort refuses. Absent both, the unfiltered anchored lane is unchanged (`matchCount` null)." priceListEntries(filter: FilterInput, sort: SortInput, priceListId: ID!, limit: Int, nextToken: String): PriceListEntryPage! "A Consumer by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." consumer(id: ID!): Consumer "The caller's org-group family's ACTIVE LISTING of Consumers — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." consumers(limit: Int, nextToken: String): ConsumerPage! "A ConsentPurpose by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." consentPurpose(id: ID!): ConsentPurpose "The caller's org-group family's ACTIVE LISTING of ConsentPurposes — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." consentPurposes(limit: Int, nextToken: String): ConsentPurposePage! "A ConsentRecord by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." consentRecord(id: ID!): ConsentRecord "The caller's org-group family's ACTIVE LISTING of ConsentRecords — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." consentRecords(limit: Int, nextToken: String): ConsentRecordPage! "A CsCase by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." csCase(id: ID!): CsCase "The caller's org-group family's ACTIVE LISTING of CsCases — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." csCases(limit: Int, nextToken: String): CsCasePage! "A GiftRegistry by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." giftRegistry(id: ID!): GiftRegistry "The caller's org-group family's ACTIVE LISTING of GiftRegistries — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." giftRegistries(limit: Int, nextToken: String): GiftRegistryPage! "A Review by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." review(id: ID!): Review "The caller's org-group family's ACTIVE LISTING of Reviews — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." reviews(limit: Int, nextToken: String): ReviewPage! "A TokenAccount by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." tokenAccount(id: ID!): TokenAccount "The caller's org-group family's ACTIVE LISTING of TokenAccounts — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TokenAccount roster: `caption` (text) · `status` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." tokenAccounts(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TokenAccountPage! "A TokenPurchase by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." tokenPurchase(id: ID!): TokenPurchase "The caller's org-group family's ACTIVE LISTING of TokenPurchases — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TokenPurchase roster: `caption` (text) · `status` (enum) · `volumeTierCode` (text) · `stripePaymentIntentId` (text) · `settledAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." tokenPurchases(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TokenPurchasePage! "A BillingCharge by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." billingCharge(id: ID!): BillingCharge "The caller's org-group family's ACTIVE LISTING of BillingCharges — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared BillingCharge roster: `caption` (text) · `status` (enum) · `periodMonth` (text) · `stripePaymentIntentId` (text) · `settledAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." billingCharges(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): BillingChargePage! "A Task by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." task(id: ID!): Task "The caller's org-group family's ACTIVE LISTING of Tasks — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). FILTERS: `status` — Only tasks in THIS FSM status (open | in_progress | postponed | completed | cancelled — the inbox surfaces default to the LIVE states client-side; cancelled is the doomed class). `assigneeUserId` — Only tasks whose assigneeUserIds contain THIS User. `labelId` — Only tasks whose labelIds contain THIS TaskLabel. `dueBefore` — Only tasks with dueAt strictly BEFORE this ISO-8601 instant. STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Task roster: `caption` (text) · `status` (enum) · `priority` (enum) · `description` (text) · `createdBy` (ref) · `reportTo` (ref) · `dueAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null). ⚠ The flat filters and the structured `filter`/`sort` do NOT combine — a read passing both refuses VALIDATION/INVALID naming the mix (compose the whole ask as filter clauses, or use the flat filters alone)." tasks(filter: FilterInput, sort: SortInput, status: String, assigneeUserId: ID, labelId: ID, dueBefore: String, limit: Int, nextToken: String): TaskPage! "A Team by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." team(id: ID!): Team "The caller's org-group family's ACTIVE LISTING of Teams — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Team roster: `caption` (text) · `status` (enum) · `leadUserId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." teams(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TeamPage! "A TaskLabel by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." taskLabel(id: ID!): TaskLabel "The caller's org-group family's ACTIVE LISTING of TaskLabels — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared TaskLabel roster: `caption` (text) · `status` (enum) · `color` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." taskLabels(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): TaskLabelPage! "A Device by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." device(id: ID!): Device "The caller's org-group family's ACTIVE LISTING of Devices — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Device roster: `caption` (text) · `status` (enum) · `deviceType` (enum) · `registerId` (ref) · `parentId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." devices(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DevicePage! "A DevicePeripheral by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." devicePeripheral(id: ID!): DevicePeripheral "The caller's org-group family's ACTIVE LISTING of DevicePeripherals — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared DevicePeripheral roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `peripheralType` (enum) · `model` (enum) · `connection` (enum) · `readerRef` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." devicePeripherals(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DevicePeripheralPage! "A ApiKey by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." apiKey(id: ID!): ApiKey "The caller's org-group family's ACTIVE LISTING of ApiKeys — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared ApiKey roster: `caption` (text) · `parentId` (ref) · `expiresAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." apiKeys(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ApiKeyPage! "A Scratchpad by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." scratchpad(id: ID!): Scratchpad "The caller's org-group family's ACTIVE LISTING of Scratchpads — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." scratchpads(limit: Int, nextToken: String): ScratchpadPage! "A Suggestion by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." suggestion(id: ID!): Suggestion "The caller's org-group family's ACTIVE LISTING of Suggestions — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Suggestion roster: `caption` (text) · `status` (enum) · `skill` (enum) · `parentId` (ref) · `schemaId` (ref) · `dedupKey` (text) · `expiresAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." suggestions(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SuggestionPage! "A SuggestionSchema by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." suggestionSchema(id: ID!): SuggestionSchema "The caller's org-group family's ACTIVE LISTING of SuggestionSchemas — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared SuggestionSchema roster: `caption` (text) · `status` (enum) · `skill` (enum) · `parentId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." suggestionSchemas(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SuggestionSchemaPage! "A Consultation by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." consultation(id: ID!): Consultation "The caller's org-group family's ACTIVE LISTING of Consultations — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Consultation roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `followOnOfId` (ref) · `idleArchiveAt` (date) · `turnsTierAt` (date) · `turnsTier` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." consultations(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): ConsultationPage! "A WebhookSubscription by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." webhookSubscription(id: ID!): WebhookSubscription "The caller's org-group family's ACTIVE LISTING of WebhookSubscriptions — doomed records DROP from listings." webhookSubscriptions: [WebhookSubscription!]! "A Plugin by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." plugin(id: ID!): Plugin "The caller's org-group family's ACTIVE LISTING of Plugins — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." plugins(limit: Int, nextToken: String): PluginPage! "A OrgPlugin by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." orgPlugin(id: ID!): OrgPlugin "The caller's org-group family's ACTIVE LISTING of OrgPlugins — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." orgPlugins(limit: Int, nextToken: String): OrgPluginPage! "A FeedSubscription by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." feedSubscription(id: ID!): FeedSubscription "The caller's org-group family's ACTIVE LISTING of FeedSubscriptions — doomed records DROP from listings." feedSubscriptions: [FeedSubscription!]! "A FraudAlert by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." fraudAlert(id: ID!): FraudAlert "The caller's org-group family's ACTIVE LISTING of FraudAlerts — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." fraudAlerts(limit: Int, nextToken: String): FraudAlertPage! "A PrivacyRequest by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." privacyRequest(id: ID!): PrivacyRequest "The caller's org-group family's ACTIVE LISTING of PrivacyRequests — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." privacyRequests(limit: Int, nextToken: String): PrivacyRequestPage! "A PolicyValueRecord by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." policyValue(id: ID!): PolicyValueRecord "The caller's org-group family's ACTIVE LISTING of PolicyValues — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." policyValues(limit: Int, nextToken: String): PolicyValueRecordPage! "A CouponBatch by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." couponBatch(id: ID!): CouponBatch "The caller's org-group family's ACTIVE LISTING of CouponBatches — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." couponBatches(limit: Int, nextToken: String): CouponBatchPage! "A Segment by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." segment(id: ID!): Segment "The caller's org-group family's ACTIVE LISTING of Segments — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Segment roster: `caption` (text) · `status` (enum) · `segmentType` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." segments(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SegmentPage! "A Dashboard by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." dashboard(id: ID!): Dashboard "The caller's org-group family's ACTIVE LISTING of Dashboards — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Dashboard roster: `caption` (text) · `status` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." dashboards(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): DashboardPage! "A Report by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." report(id: ID!): Report "The caller's org-group family's ACTIVE LISTING of Reports — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." reports(limit: Int, nextToken: String): ReportPage! "A Collaborator by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." collaborator(id: ID!): Collaborator "The caller's org-group family's ACTIVE LISTING of Collaborators — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." collaborators(limit: Int, nextToken: String): CollaboratorPage! "A SchedulableResource by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." schedulableResource(id: ID!): SchedulableResource "The caller's org-group family's ACTIVE LISTING of SchedulableResources — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared SchedulableResource roster: `caption` (text) · `status` (enum) · `resourceType` (enum) · `parentId` (ref) · `userId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." schedulableResources(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SchedulableResourcePage! "A Appointment by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." appointment(id: ID!): Appointment "The caller's org-group family's ACTIVE LISTING of Appointments — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Appointment roster: `caption` (text) · `status` (enum) · `purpose` (enum) · `parentId` (ref) · `variantId` (ref) · `orderId` (ref) · `startAt` (date) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." appointments(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): AppointmentPage! "A Storefront by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." storefront(id: ID!): Storefront "The caller's org-group family's ACTIVE LISTING of Storefronts — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared Storefront roster: `caption` (text) · `status` (enum) · `theme` (enum) · `parentId` (ref) · `logicalFacilityId` (ref) · `customDomain` (text) · `categoryId` (ref) · `divisionId` (ref) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." storefronts(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): StorefrontPage! "A AgentChannel by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." agentChannel(id: ID!): AgentChannel "The caller's org-group family's ACTIVE LISTING of AgentChannels — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared AgentChannel roster: `caption` (text) · `status` (enum) · `parentId` (ref) · `logicalFacilityId` (ref) · `priceListId` (ref) · `divisionId` (ref) · `rateClass` (enum) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." agentChannels(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): AgentChannelPage! "A SearchJob by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." searchJob(id: ID!): SearchJob "The caller's org-group family's ACTIVE LISTING of SearchJobs — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." searchJobs(limit: Int, nextToken: String): SearchJobPage! "A ExportJob by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." exportJob(id: ID!): ExportJob "The caller's org-group family's ACTIVE LISTING of ExportJobs — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." exportJobs(limit: Int, nextToken: String): ExportJobPage! "A SizeRun by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." sizeRun(id: ID!): SizeRun "The caller's org-group family's ACTIVE LISTING of SizeRuns — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page). STRUCTURED FILTER + SORT: `filter` = AND across clauses, OR within a clause's values; `sort` = one declared field, asc/desc. The declared SizeRun roster: `caption` (text) · `status` (enum) · `optionGroupId` (ref) · `code` (text) · `createdAt` (date) · `updatedAt` (date). An illegal filter/sort refuses VALIDATION/INVALID NAMING the exact problem (an unknown field teaches the roster). A filtered/sorted read evaluates the WHOLE family server-side, returns the EXACT `matchCount`, and its `nextToken` binds to THE ONE filter+sort that minted it — replaying it under a different filter/sort refuses. Absent both, the unfiltered lane is unchanged (`matchCount` null)." sizeRuns(filter: FilterInput, sort: SortInput, limit: Int, nextToken: String): SizeRunPage! "A TrainingRequirement by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." trainingRequirement(id: ID!): TrainingRequirement "The caller's org-group family's ACTIVE LISTING of TrainingRequirements — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." trainingRequirements(limit: Int, nextToken: String): TrainingRequirementPage! "A TrainingQuestion by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." trainingQuestion(id: ID!): TrainingQuestion "The caller's org-group family's ACTIVE LISTING of TrainingQuestions — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." trainingQuestions(limit: Int, nextToken: String): TrainingQuestionPage! "A TrainingAttempt by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." trainingAttempt(id: ID!): TrainingAttempt "The caller's org-group family's ACTIVE LISTING of TrainingAttempts — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." trainingAttempts(limit: Int, nextToken: String): TrainingAttemptPage! "A TrainingCertificate by id, within the caller's OWN org-group family; requires authentication. A cross-tenant id reads as null (not-found) AND trips the rootId tripwire server-side." trainingCertificate(id: ID!): TrainingCertificate "The caller's org-group family's ACTIVE LISTING of TrainingCertificates — doomed records DROP from listings. PAGINATED: `limit` clamps to [1, 200], default 100; `nextToken` = the prior page's cursor, verbatim — opaque + tenant-bound (a malformed or foreign token → VALIDATION/INVALID). Walk until `nextToken` is null (a page may hold fewer than `limit` — doomed drop per page)." trainingCertificates(limit: Int, nextToken: String): TrainingCertificatePage! } type Mutation { "Reserved for the platform; not available to API keys." login(loginName: String!, password: String!, orgId: ID!): LoginResult! "Revoke the caller's current session — idempotent; the next call with the token dies." logout: Boolean! "THE MERCHANT’S DOOR: open ONE user’s sealed activity trail for ONE window (ISO instants, at most 7 days) with a reason (1–256 characters). the ledger-first rule: the opening is recorded — the ledger row + the permanent log event — BEFORE any row is unsealed; no record, no unseal. Answers the timeline in time order (time · app · build · screen · op · outcome · milliseconds · call id · session). OWNER-ONLY (the A19_TRAIL area). VALIDATION/INVALID on a bad window or a blank reason." userActivityTrail(userId: ID!, from: String!, to: String!, reason: String!): UserActivityTrail! "Create an Organization + its ENTIRE min-1 facility chain in the caller's org group — the CostCentre + the org + the first PF (referencing an EXISTING active PFL, tenant-scoped server-side) + first LF + first Zone + first Bin, in ONE atomic operation; requires the unrestricted capability." createOrganization(input: NewOrganizationInput!): OrganizationCreation! "Edit an Organization's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A primaryPhysicalFacility re-designation is guarded (in-tenant + belongs-to-this-org + active) and implicitly releases the old designation." updateOrganization(id: ID!, revision: ID!, input: EditOrganizationInput!): Organization! "PROVISION the org's Stripe Connect account: creates the account (the Standard production shape — Stripe-hosted onboarding via createStripeOnboardingLink) and stamps stripeAccountRef/stripeChargesEnabled/stripeDetailsSubmitted in ONE revision. An already-provisioned org refuses CONFLICT/REFERENCED (the ref is IMMUTABLE); a dark org refuses CONFLICT/REF_STATE; a processor refusal maps VALIDATION/INVALID naming the reason (nothing stamped — the adapter's org-keyed idempotency makes a retry converge on the SAME account). testProgrammatic = the DVLP arm (sk_test-only, US-only): the API-completable TEST shape for AFK E2E — structurally dead at PROD LOCK. Requires the unrestricted capability + the CURRENT revision (OCC)." provisionStripeAccount(id: ID!, revision: ID!, testProgrammatic: Boolean): Organization! "Mint an EPHEMERAL Stripe-hosted onboarding link for the org's connected account. Unprovisioned refuses CONFLICT/REF_STATE; a processor refusal maps CONFLICT/RECONCILE (retryable — the stored ref and the processor disagree). Requires the unrestricted capability. No revision — this mutates NOTHING on the record." createStripeOnboardingLink(id: ID!): StripeOnboardingLink! "Pull the connected account's CURRENT charges_enabled/details_submitted and re-stamp the org. Unprovisioned refuses CONFLICT/REF_STATE; a processor read failure maps CONFLICT/RECONCILE (retryable). Requires the unrestricted capability + the CURRENT revision (OCC)." refreshStripeAccountStatus(id: ID!, revision: ID!, reason: String): Organization! "Copy a canned Characteristic template into the caller's org group; requires the unrestricted capability." copyCannedCharacteristic(input: CopyCannedCharacteristicInput!): Characteristic! "Create an ITEM — a zero-dimension simple Style + its whole-style Product + the single Variant — in ONE atomic transaction; requires the unrestricted capability. Returns the full trio." createItem(input: NewItemInput!): ItemCreation! "ASSIGN an identifier to a Variant; requires the unrestricted capability. Refusals: a burned SKU → CONFLICT/SKU_TAKEN naming the holder (+holderProduct); a live plu/gtin holder → CONFLICT/IDENTITY_TAKEN (gtin carries overridable: true — pass override to displace); org-scoped kinds gate on an ACTIVE OrgStyle selection of the variant's style (CONFLICT/UNSELECTED — the gate); the identical current value → VALIDATION/INVALID." assignIdentifier(input: AssignIdentifierInput!): IdentifierEntry! "RETIRE the variant's CURRENT identifier of a kind. No current entry → NOT_FOUND/IDENTIFIER. Requires the unrestricted capability." retireIdentifier(input: RetireIdentifierInput!): IdentifierEntry! "VOID one ledger entry. Refused while the bearer variant is doomed (frozen history → CONFLICT/REF_STATE). Requires the unrestricted capability + the entry's CURRENT revision." voidIdentifierEntry(id: ID!, revision: ID!, reason: String): IdentifierEntry! "RECEIVE stock onto an InventoryItem. The II must be ACTIVE (CONFLICT/REF_STATE else) and STOCKED (a service/bundle II is VALIDATION/INVALID naming its styleType — IV-c); the unit-cost currency must match the II cost currency once fixed (VALIDATION/INVALID naming the expected currency). Movements thread NO revision (the ledger-posting stance); a raced concurrent movement is retryable CONFLICT/REVISION_STALE. Requires the unrestricted capability." receiveStock(input: ReceiveStockInput!): StockMovement! "ADJUST stock (± write-on/write-off, reason-coded) in ONE atomic transaction. Same gates as receiveStock (ACTIVE + STOCKED); the bucket must be -movable (on_hand | damaged | held, named refusal); going negative is ALLOWED + stamps overcommitted on the entry; value moves at the CURRENT WMA. Requires the unrestricted capability." adjustStock(input: AdjustStockInput!): StockMovement! "RECLASS stock bucket-to-bucket (same total, NO value change; on_hand | damaged | held) in ONE atomic transaction. Same gates as receiveStock (ACTIVE + STOCKED); a reclass into held REQUIRES a canned heldReason; draining a bucket below zero is ALLOWED + stamps overcommitted. Requires the unrestricted capability." reclassStock(input: ReclassStockInput!): StockMovement! "BUILD kits from component stock. The named II must be ACTIVE + kit-TYPED (bundles NEVER build; VALIDATION/INVALID naming the styleType); the BOM must be non-empty and within the 49-component transaction bound; every component variant ACTIVE + its II existing at the SAME facility (movements never auto-vivify, IV-b). Consuming below zero is ALLOWED + stamps overcommitted per leg. Movements thread NO revision; a raced concurrent movement is retryable CONFLICT/REVISION_STALE. Requires the unrestricted capability." buildStock(input: BuildStockInput!): StockAssembly! "BREAK kits back into component stock. Requires the unrestricted capability." breakStock(input: BreakStockInput!): StockAssembly! "RELOCATE stock between locations of ONE InventoryItem in ONE atomic transaction: the cache-NEUTRAL relocate entry + the touched StockRecord shard writes (create-on-demand at the target). Same gates as receiveStock (ACTIVE + STOCKED); the to-bin must be ACTIVE and both bins in the item logical facility; driving a record or the un-binned pool negative refuses CONFLICT/INSUFFICIENT_STOCK naming the location; lot fields only on lot-controlled items. Movements thread NO revision; a raced concurrent movement or record write is retryable CONFLICT/REVISION_STALE. Requires the unrestricted capability." relocateStock(input: RelocateStockInput!): StockMovement! "REPAIR one junction's on-order figure: re-derive the InventoryItem's onOrderQty from the receivable purchase orders' open lines for its variant × logical facility and stamp THAT figure over the stored one — ONE OCC full-item write with the REQUIRED reason on the revision cause (kind edit); a converged cell answers changed false and writes nothing. No stock moves and no Stock-Card entry posts — on order is bookkeeping beside the five buckets, never a bucket. 'reason' is REQUIRED and non-blank (blank/oversize refuse VALIDATION/INVALID naming the cure). Requires the unrestricted capability." repairInventoryOnOrder(id: ID!, reason: String!): InventoryOnOrderRepair! "CREATE a Transfer: lines FIXED at create (1..24 NAMED; distinct source IIs, each ACTIVE + STOCKED with its destination junction EXISTING at the destination LF — movements never auto-vivify, IV-b); both LFs ACTIVE; a same-LF pair refuses (relocateStock is the intra-LF sibling); the weight + org attribution derive from the live LF-PF-PFL spine and stamp IMMUTABLE." createTransfer(input: CreateTransferInput!): Transfer! "SUBMIT a draft Transfer: SHIPPED reserves each line's source stock as an ENTRY-LESS doc-backed claim (reserved += q) refusing CONFLICT/INSUFFICIENT_STOCK at location facility when available < q; LIGHT completes in this ONE step (both legs posted immediately — no reserve, no in_transit; immediate handoff). Both LFs must be ACTIVE (CONFLICT/REF_STATE else); requires the doc CURRENT revision (OCC) + the unrestricted capability." submitTransfer(id: ID!, revision: ID!, reason: String): Transfer! "SHIP a ready Transfer (ready -> in_transit): per line ONE transfer_out entry @src (on_hand-, relief at the source CURRENT WMA — its book unchanged) + ONE transfer_in entry @dest (in_transit+ at VALUE-AT-SHIP q x srcWMA; the dest WMA re-weights; the currency birth law applies NAMED) + the reserved claim release, ALL in ONE transaction with the doc rollups + the optional ship metadata. Re-verifies PRESENT stock (reserved >= q AND on_hand >= q — CONFLICT/INSUFFICIENT_STOCK at location facility). Both LFs ACTIVE; requires the doc CURRENT revision (OCC) + the unrestricted capability." shipTransfer(input: ShipTransferInput!, revision: ID!, reason: String): Transfer! "RECEIVE against an in-transit Transfer (partial + repeatable): per landing ONE value-NEUTRAL transfer_in entry @dest (in_transit -> on_hand | held reason-coded) + the doc rollup stamps. Completing every line chains to received emitting receive.ok ONCE; an incomplete receive from partially_received stamps rollups WITHOUT a state change. UNDECLARED over-receipt refuses CONFLICT/DISCREPANCY — the / DECLARED lanes ride the same call: surplus books dest+ at the line's FROZEN at-ship unit cost (stamps unplannedQty; never the source book — custody), wrong-item arrivals book QTY-ONLY at a named dest-LF junction; FSM edges derive ONLY from ordinary receipts (a receipts-empty call posts movements without touching the doc status). The LF-status matrix HEALS here (any status — in-transit stock must land); the destination IIs must be ACTIVE (CONFLICT/REF_STATE else — reactivation is free). Requires the doc CURRENT revision (OCC) + the unrestricted capability." receiveTransfer(input: ReceiveTransferInput!, revision: ID!, reason: String): Transfer! "RESOLVE a short/lost/damaged Transfer: EVERY residual disposed in this ONE step via disposition-coded doc-referencing movements (loss / scrap = adjust in_transit- at the dest CURRENT WMA — scrap is the deliberate-disposal twin, damaged / found = value-neutral reclass to damaged / on_hand; returned = the pair: dest relief at the dest CURRENT WMA + the SOURCE book-in at the line's FROZEN at-ship unit cost, WMA recomputed exactly as a dest receive would — the value-conserving round trip; goods returned AFTER receipt ride an ordinary NEW reverse Transfer instead). An incomplete disposition set refuses CONFLICT/UNRESOLVED naming the residuals; over-disposal refuses NAMED; the composed call must fit the one-transaction action budget. Heals across LF status; destination IIs must be ACTIVE — and the returned lines' SOURCE IIs too (they receive the residual). Requires the doc CURRENT revision (OCC) + the unrestricted capability." resolveTransfer(input: ResolveTransferInput!, revision: ID!, reason: String): Transfer! "CLOSE a fully-received Transfer (received -> closed): the leg-less success finalization — the reconciled gate re-derives the residuals DEFENSIVELY (drift refuses CONFLICT/UNRESOLVED, the close.unreconciled form). Heals across LF status. Requires the doc CURRENT revision (OCC) + the unrestricted capability." closeTransfer(id: ID!, revision: ID!, reason: String): Transfer! "CANCEL a Transfer BEFORE ship: draft / pending_send_approval cancel pure-FSM; ready RELEASES the reserved claims (reserved -= q per line; ANY II status — the healing direction). cancelled is the ONE doomed terminal (lists filter it; revival is a NEW Transfer). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelTransfer(id: ID!, revision: ID!, reason: String): Transfer! "CREATE a TransferRequest: lines FIXED at create (1..24 NAMED — TR-o; distinct variants, each resolving an EXISTING requesting-LF InventoryItem junction — IV-b demand-side, refusal NAMED {lineNo, variantId, logicalFacilityId}); the requesting LF ACTIVE (+ the target LF resolvable when named; target == requesting refuses); the org attribution derives from the live spine and stamps IMMUTABLE." createTransferRequest(input: CreateTransferRequestInput!): TransferRequest! "SUBMIT a draft TransferRequest: re-gates the requesting LF ACTIVE + every line junction ACTIVE, then the TR-e sourcing-eligibility arm — targeted: the target LF ACTIVE +!= requesting; open: >= 1 ACTIVE group LF!= requesting; NO eligible source refuses CONFLICT/NO_SOURCE (RETRYABLE — the doc stays draft, editable/cancelable; cure by activating/creating an LF and retry). Requires the doc CURRENT revision (OCC) + the unrestricted capability." submitTransferRequest(id: ID!, revision: ID!, reason: String): TransferRequest! "ACCEPT lines of an OPEN TransferRequest: ONE TransactWriteItems births ONE linked Transfer at ready (create+submit fusion — the claims reserve the source stock, holding the accepting-reserves law; a LIGHT pair births completed, posting BOTH legs immediately) + the request allocation-rollup rewrite LAST under the request OCC (the doc IS the allocation serializer — raced accepts are retryable CONFLICT/REVISION_STALE). The full.1 birth gates ride (source LF ACTIVE +!= requesting; per line the source II [variant x source LF] ACTIVE + STOCKED + junction-EXISTING; available >= q or CONFLICT/INSUFFICIENT_STOCK at location facility); a foreign source on a TARGETED request refuses NAMED; cumulative over-allocation refuses CONFLICT/DISCREPANCY {lineNo, outstanding, supplied}. Returns BOTH documents (TR-p). Requires the doc CURRENT revision (OCC) + the unrestricted capability." acceptTransferRequest(input: AcceptTransferRequestInput!, revision: ID!, reason: String): AcceptTransferRequestResult! "REJECT (decline) lines of an OPEN TransferRequest: bounded informational markers under the request OCC — no FSM move, no quantity effect, no reservation (<= 8 per line, ONE per declining source — a duplicate decline refuses). A partial reject = accept-part + reject-rest. A foreign source on a TARGETED request refuses NAMED. Requires the doc CURRENT revision (OCC) + the unrestricted capability." rejectTransferRequest(input: RejectTransferRequestInput!, revision: ID!, reason: String): TransferRequest! "CLOSE an open TransferRequest SHORT: refused CONFLICT/IN_PROGRESS naming the first-8 live linked Transfers while ANY is non-terminal (in-transit stock must land first — an immutable terminal may never strand a linked receive); after it, the doc is IMMUTABLE non-doomed history. Requires the doc CURRENT revision (OCC) + the unrestricted capability." closeShortTransferRequest(id: ID!, revision: ID!, reason: String): TransferRequest! "CANCEL a TransferRequest: draft / submitted cancel pure-FSM; open-cancel refuses CONFLICT/IN_PROGRESS when any line has shipped quantity OR any linked Transfer is live (the generalized has_shipments row; policy:reservations_released re-derives all-linked-terminal DEFENSIVELY). cancelled is the ONE doomed terminal (lists filter it; revival is a NEW TransferRequest). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelTransferRequest(id: ID!, revision: ID!, reason: String): TransferRequest! "CREATE a Count: the SELECTOR + countType + recountOf BIRTH-FIXED; the LF scoped + ACTIVE (STRICT birth); selector members scoped to that LF STATUS-FREE (counting an inactive zone/bin is legitimate — heal); recountOf must resolve to a POSTED count at the SAME LF; the org attribution derives from the live spine and stamps IMMUTABLE. Lines land at START." createCount(input: CreateCountInput!): Count! "START a draft Count: resolves the selector ONCE to concrete lines (the scope's StockRecord shards [(II x bin x lot) — lot lines ride the records free] + whole-LF-only un-binned POOL lines), snapshots each line's on_hand, and FREEZES the line set. An EMPTY resolution refuses VALIDATION/EMPTY_SCOPE (the DECLARED start.empty_scope form — emits); an over-ceiling one refuses event-less NAMED {resolved, max: 32}. Re-gates the LF ACTIVE. Requires the doc CURRENT revision (OCC) + the unrestricted capability." startCount(id: ID!, revision: ID!, reason: String): Count! "CAPTURE counted quantities onto a COUNTING Count: point-reads each captured line's live on_hand and stamps {countedQty, expectedAtCapture, capturedAt} together under the doc OCC — a rollup-only revision, NO FSM event (the receive-rollup precedent). Repeatable; a re-capture OVERWRITES the line's trio while counting (the fat-finger cure); an explicit ZERO is a legitimate capture; unknown lineNos refuse NAMED. The LF is never re-gated here (heal). Requires the doc CURRENT revision (OCC) + the unrestricted capability." captureCount(input: CaptureCountInput!, revision: ID!, reason: String): Count! "POST a fully-captured Count: posts every NON-ZERO variance as a count_correct DELTA through ONE transaction — gain to / shrink from on_hand; record lines stamp their StockRecord in the SAME transaction (the SECOND record-touching movement); pool lines post bin-blind (the pool re-derives); costImpact = variance x the II's CURRENT WMA (shrink −/gain +; the WMA itself never re-weights on a count) + unitCost = that WMA + refs [IC-sysId] on EVERY entry (never-silent). Uncaptured lines refuse event-less naming the first-8 lineNos; every varianced line's II must be ACTIVE (CONFLICT/REF_STATE — reactivation free); a ZERO-variance posting is LEG-LESS (pure FSM — posted with no movements). Requires the doc CURRENT revision (OCC) + the unrestricted capability." postCount(id: ID!, revision: ID!, reason: String): Count! "CANCEL a Count: cancelled is the ONE doomed terminal (lists filter it; point-readable; revival is a NEW Count). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelCount(id: ID!, revision: ID!, reason: String): Count! "CREATE a PurchaseOrder: ONE ACTIVE OrgVendor (IMMUTABLE; a paused enablement refuses CONFLICT/REF_STATE); currency = its purchasingCurrency SNAPSHOT (UNSET refuses VALIDATION/INVALID naming it); per line — the variant tenant-scoped + ACTIVE + stocked (service/bundle styles refuse), the receiving LF (line value?? the OrgVendor defaultShipToLogicalFacilityId; NEITHER refuses NAMED) ACTIVE + belonging to the BUYING org, the unit cost (line value?? the OVI listCost via the O(1) pair point-read; NEITHER refuses NAMED) in the PO currency, requireCatalogItem ⇒ a LIVE OVI per line, line quantity ≥ the OVI moq; the arrival defaults create-date + (OVI?? OrgVendor) leadTimeDays." createPurchaseOrder(input: CreatePurchaseOrderInput!): PurchaseOrder! "SUBMIT a draft PurchaseOrder for spend approval (draft -> pending_approval, policy:spend_over_threshold): DECLARED-UNREACHABLE until the policy chain builds — no spend-threshold policy engages, so the step refuses its declared VALIDATION/INVALID form (the transfer pending_send_approval precedent); issue directly instead. Requires the doc CURRENT revision (OCC) + the unrestricted capability." submitPurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "ISSUE a draft PurchaseOrder to its vendor (draft -> issued, policy:no_approval_required + referential_integrity): the consumer gates RE-RUN — the OrgVendor still ACTIVE, every line's variant + receiving LF ACTIVE, requireCatalogItem ⇒ a LIVE OVI per line, line quantity ≥ the OVI moq, and Σ line merchandise value ≥ the OrgVendor orderMinimum. Receipts may post after. Requires the doc CURRENT revision (OCC) + the unrestricted capability." issuePurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "APPROVE a pending PurchaseOrder (pending_approval -> issued, authority:approve_po): an unreachable-state step until builds the spend-threshold policy (nothing can reach pending_approval); declared for the day it does. Requires the doc CURRENT revision (OCC) + the unrestricted capability." approvePurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "REJECT a pending PurchaseOrder back to draft (pending_approval -> draft, authority:approve_po): the approval bounce — an unreachable-state step until. Requires the doc CURRENT revision (OCC) + the unrestricted capability." rejectPurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "ACKNOWLEDGE an issued PurchaseOrder (issued -> acknowledged): the OPTIONAL vendor-acknowledgement waypoint — manual capture (no vendor integration exists); receipts post from either state. Requires the doc CURRENT revision (OCC) + the unrestricted capability." acknowledgePurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "CLOSE a partially-received PurchaseOrder SHORT (partially_received -> closed_short): the backorder exit — the outstanding is cancelled; immutable NON-doomed history after. Requires the doc CURRENT revision (OCC) + the unrestricted capability." closeShortPurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "CANCEL a PurchaseOrder (draft/pending_approval pure-FSM; issued gated policy:no_receipts_yet — any POSTED receipt or line rollup refuses CONFLICT/IN_PROGRESS naming first-8; close_short IS the exit once receiving starts): cancelled is the ONE doomed terminal (lists filter it; revival is a NEW PO). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelPurchaseOrder(id: ID!, revision: ID!, reason: String): PurchaseOrder! "APPEND lines to a DRAFT PurchaseOrder: the same per-line gates as create (the variant tenant-scoped + ACTIVE + stocked, the receiving LF ACTIVE + owned by the BUYING org, the unit cost in the PO currency, requireCatalogItem ⇒ a LIVE OVI, quantity ≥ the OVI moq); the DISTINCT variant × receiving-LF law holds over the WHOLE document (a key already on the order refuses VALIDATION/INVALID naming the holding lineNo); lineNo mints from the monotonic nextLineNo; the document total refuses past the ceiling. ONE transaction — the row Puts + the header rollups. A live post-draft doc refuses CONFLICT/REF_STATE. Requires the doc CURRENT revision (OCC) + the unrestricted capability. NO reason — the edit class." addPurchaseOrderLines(input: AddPurchaseOrderLinesInput!, revision: ID!): PurchaseOrder! "REPLACE ONE line of a DRAFT PurchaseOrder WHOLE: the addressed lineNo is KEPT, every create-time gate re-runs on the replacement, and the header rollups move with it. ONE transaction — the row Put + the header rewrite. A live post-draft doc refuses CONFLICT/REF_STATE; an unknown lineNo refuses VALIDATION/INVALID naming it. Requires the doc CURRENT revision (OCC) + the unrestricted capability. NO reason — the edit class." updatePurchaseOrderLine(input: UpdatePurchaseOrderLineInput!, revision: ID!): PurchaseOrder! "REMOVE lines from a DRAFT PurchaseOrder: the rows are deleted, their lineNo gaps STAY and the numbers are NEVER re-used (so Receipt / VendorInvoice poLineNo addressing keeps its meaning forever); a line carrying a special-order orderLineRef refuses CONFLICT/REFERENCED (the standing protection — unlink the demand line first). ONE transaction — the row Deletes + the header rollups. A live post-draft doc refuses CONFLICT/REF_STATE. Requires the doc CURRENT revision (OCC) + the unrestricted capability. NO reason — the edit class." removePurchaseOrderLines(input: RemovePurchaseOrderLinesInput!, revision: ID!): PurchaseOrder! "CREATE a Receipt: the parent PO RECEIVABLE (issued/acknowledged/partially_received); the receiving LF tenant-scoped + ACTIVE + named by ≥1 PO line; every line addresses a PO line destined to THIS LF (one line per PO-line × disposition; a hold is reason-coded — the law, strict both ways); estimate components ≤8 in the PO currency; up to 90 lines per call (a receipt holds up to 1000 — add more with addReceiptLines)." createReceipt(input: CreateReceiptInput!): Receipt! "POST a draft Receipt (draft -> posted, -e — 🧱 /: THE WHOLE-DOCUMENT JUDGEMENT first (every gate over every line and every junction BEFORE any write), then the lines land in stock through the chokepoint a chunk at a time under the 100-action transaction budget: a small receipt lands posted in ONE TransactWriteItems; a large one WALKS — draft -> posting -> posted under the document-walk machine — the status reads posting until every line has landed, the header carries the walk (kind post · cursor = the next lineNo to land · chunks · lineCount), a healthy in-flight walk refuses a second post CONFLICT/IN_PROGRESS and re-running post RESUMES a stalled one; a second receipt posting against the SAME PO while one is in flight refuses CONFLICT/IN_PROGRESS naming it (the PO's receivingReceiptId); an EMPTY line set refuses VALIDATION/INVALID): per line a receive movement into on_hand at the LANDED unit cost (the estimate components allocate exactly via allocateProportionally in line order — -h; the value-form re-weight; the currency law gates every touched book) + a disposition reclass companion (hold -> held reason-coded / damage -> damaged — receive lands on_hand ONLY, the law) + missing (variant × LF) junction BIRTHS via the catalogued create-on-receive hatch + StockRecord bin stamps for binned lines + the per-line merchandise/landed split STAMPED on the posted doc + the parent-PO rollup and its system:receipt_posted / system:all_received chain riding the SAME transaction. The LF is ACTIVE-re-checked (SL-b use-time). Over-receipt (cumulative > ordered per PO line) refuses CONFLICT/THREE_WAY_MATCH — the PO's declared receive.match_flag form. Partial receipts are first-class — the next arrival is a NEW Receipt. Requires the doc CURRENT revision (OCC) + the unrestricted capability." postReceipt(id: ID!, revision: ID!, reason: String): Receipt! "CANCEL a draft Receipt (draft -> cancelled pure-FSM — an abandoned draft never moved stock): cancelled is the doomed terminal (lists filter it; a new arrival is a NEW Receipt). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelReceipt(id: ID!, revision: ID!, reason: String): Receipt! "APPEND lines to a DRAFT Receipt: the same per-line gates as create (the parent PO still RECEIVABLE, every poLineNo an existing PO line destined to THIS receipt's LF, a hold reason-coded, the pack pair variant-coherent); the DISTINCT (PO line × disposition) law holds over the WHOLE document (a key already on the receipt refuses VALIDATION/INVALID naming the holding lineNo); lineNo mints from the monotonic nextLineNo; the document total refuses past the ceiling. ONE transaction — the row Puts + the header rollups. A live post-draft doc refuses CONFLICT/REF_STATE. Requires the doc CURRENT revision (OCC) + the unrestricted capability. NO reason — the edit class." addReceiptLines(input: AddReceiptLinesInput!, revision: ID!): Receipt! "REPLACE ONE line of a DRAFT Receipt WHOLE: the addressed lineNo is KEPT, every create-time gate re-runs on the replacement, and the header rollups move with it. ONE transaction — the row Put + the header rewrite. A live post-draft doc refuses CONFLICT/REF_STATE; an unknown lineNo refuses NOT_FOUND naming it. Requires the doc CURRENT revision (OCC) + the unrestricted capability. NO reason — the edit class." updateReceiptLine(input: UpdateReceiptLineInput!, revision: ID!): Receipt! "REMOVE lines from a DRAFT Receipt: the rows are deleted, their lineNo gaps STAY and the numbers are NEVER re-used (the address keeps its meaning forever). ONE transaction — the row Deletes + the header rollups. A live post-draft doc refuses CONFLICT/REF_STATE; an unknown number refuses NOT_FOUND naming it. Requires the doc CURRENT revision (OCC) + the unrestricted capability. NO reason — the edit class." removeReceiptLines(input: RemoveReceiptLinesInput!, revision: ID!): Receipt! "CREATE an Rtv: ONE ACTIVE OrgVendor (the parent — lean 2; PO-less overstock/recall returns are legal); the optional PO must be SAME-vendor + past-issue; the ship-from LF ACTIVE + the buying org's; per line the (variant × ship-from LF) InventoryItem junction must EXIST + be active (TR-f — an RTV of a variant never stocked at the LF is meaningless) and the expectedCredit currency must match the vendor purchasingCurrency when both exist." createRtv(input: CreateRtvInput!): Rtv! "APPROVE a draft Rtv (draft -> approved, authority:approve_rtv — a REAL maker/checker step from birth, never policy-conditional). Requires the doc CURRENT revision (OCC) + the unrestricted capability." approveRtv(id: ID!, revision: ID!, reason: String): Rtv! "SHIP an approved Rtv (approved -> shipped — ONE transaction, -f/lean 6): per line ONE rtv movement relieving its sourceBucket at the II's CURRENT WMA (costImpact = −q × WMA; the book average never moves on relief — the sell/ symmetry) + StockRecord bin stamps for binned lines (the NAMED bin must hold the stock — STRICT). PRESENT stock only — a short (II × bucket) or bin refuses CONFLICT/INSUFFICIENT_STOCK naming the location; every line junction is re-gated ACTIVE; the ship-from LF is ACTIVE-re-checked (SL-b use-time). Stamps resolvedReturnsContactId (the OrgVendor returnsToContactId?? the vendor host's SINGLE live returns-role assignment — unresolvable or ambiguous refuses NAMED) + the expectedCredit default (Σ q × WMA) when the caller never set one. Requires the doc CURRENT revision (OCC) + the unrestricted capability." shipRtv(id: ID!, revision: ID!, reason: String): Rtv! "RECORD the vendor credit (shipped -> credited via the caller_op:record_credit row — the OR-trigger split; the system:vendor_credit twin stays integration-reserved): an actualCredit ≠ the stored expectation (amount OR currency, or NO expectation stored) refuses CONFLICT/CREDIT_MISMATCH (RETRYABLE — re-record the corrected figure); acknowledgeVariance: true is the explicit cure, stamping creditVarianceAcknowledged (the variance stays reports-only — no AR/AP). Requires the doc CURRENT revision (OCC) + the unrestricted capability." recordRtvCredit(input: RecordRtvCreditInput!, revision: ID!, reason: String): Rtv! "CANCEL an Rtv (draft/approved pure-FSM — no stock moved before ship; NO cancel after ship, stock has left, the forward path is record_credit): cancelled is the ONE doomed terminal (lists filter it; revival is a NEW Rtv). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelRtv(id: ID!, revision: ID!, reason: String): Rtv! "CREATE a VendorInvoice: the parent PO past-issue (cancelled/draft/pending refuse CONFLICT/REF_STATE); the billing OrgVendor (defaulted to the PO vendor) ACTIVE; every Money in the PO snapshot currency; at-least-one-of matchLines/actualComponents (the Contact substance stance); each match line names an EXISTING PO line. The (invoiceOrgVendor × normalized invoice number) UNIQ pair mints IN the create transaction — a live (draft or captured) holder refuses CONFLICT/IDENTITY_TAKEN naming it (the double-pay gate); a cancelled holder is taken over." createVendorInvoice(input: CreateVendorInvoiceInput!): VendorInvoice! "CAPTURE a draft VendorInvoice (draft -> captured — the 3-way match + the landed TRUE-UP in ONE transaction, -g/h): per match line, CUMULATIVE captured-sibling invoiced + this vs the PO line receivedQty rollup AND invoiced unit cost vs the PO line's — tolerance ZERO, variance FLAGS matchStatus/matchFlags (first-8) and NEVER blocks. Landed ACTUALS true up against the POSTED receipts estimates of the SAME component type (first capture of a type consumes them; later bills of that type are compensating additions): the estimate allocation re-derives deterministically over the stored posted lines, and each touched book takes ONE cost_true_up value-only movement (qty 0, signed costImpact, refs [VI, PO]) re-weighting its WMA over the CURRENT cost-bearing quantity — an empty/unabsorbing book keeps its WMA (the sold-share stays a reports-only fact). A cost bill with NO posted receipt refuses VALIDATION/INVALID. Requires the doc CURRENT revision (OCC) + the unrestricted capability." captureVendorInvoice(id: ID!, revision: ID!, reason: String): VendorInvoice! "CANCEL a draft VendorInvoice (draft -> cancelled pure-FSM — an abandoned draft; the doomed terminal; the UNIQ pair releases to takeover — re-keying the same bill is a NEW doc). Requires the doc CURRENT revision (OCC) + the unrestricted capability." cancelVendorInvoice(id: ID!, revision: ID!, reason: String): VendorInvoice! "ISSUE an Invoice against a placed/completed Order: lines ⊆ the un-invoiced remainder read off the Order's OWN invoicedQty rollup stamps (omitted = the FULL remainder; an all-zero remainder refuses VALIDATION/INVALID — nothing to invoice); money figures prorate by cumulative telescoping (EXACT — a full invoicing sums to the order figures per component); taxMode captures explicit. ONE transaction: the invoice create + the Order rollup stamp under the Order's OCC. The org must be ACTIVE." issueInvoice(input: IssueInvoiceInput!): Invoice! "ISSUE a CreditNote against an issued/closed Invoice: each entry addresses one invoice line with a positive magnitude (the document supplies the − sign); over-credit refuses per line STRICT (taxableBase + Σ prior signed note deltas − credit ≥ 0 → VALIDATION/INVALID naming the line); the tax delta recomputes over the line's CAPTURED components (no re-sourcing — a FULL credit mirrors the original figures EXACTLY). NO inventory movement (a goods-back is a Return). ONE transaction: the note create + the Invoice notedBaseDeltaMinor stamp under the Invoice's OCC. The org must be ACTIVE." issueCreditNote(input: IssueCreditNoteInput!): CreditNote! "ISSUE a DebitNote against an issued/closed Invoice: sign +, NO over-credit ceiling (an increase raises the invoice's remaining net — the CreditNote guard reads the raised headroom via the same stamps); otherwise identical to issueCreditNote." issueDebitNote(input: IssueDebitNoteInput!): DebitNote! "RECEIVE an approved Return: the disposition cover addresses every NON-STOCKLESS line EXACTLY (splits across codes legal; incomplete/over/unknown refuse VALIDATION/INVALID naming residuals); restock/inspect/damaged post `return` movements at the RECEIVING LF's (variant × LF) IIs cost-entering at CURRENT WMA (the average never moves; uncosted books qty-only; a variant never stocked at the LF refuses CONFLICT/REF_STATE naming the junction); scrap posts NO movement (the write-off is reports-only). The refund money stamps by cumulative telescoping over the order line's captured figures; the restocking fee applies ONLY where the sale captured the flag. ONE transaction: the doc rewrite + the legs + the ORDER returnedQty rollup stamp under the Order's OCC (remainder = quantity − returnedQty; over refuses CONFLICT/OVER_RETURNABLE naming the line — concurrent receives serialize CONFLICT/REVISION_STALE, retryable). Requires the doc CURRENT revision (OCC) + the unrestricted capability." receiveReturn(input: ReceiveReturnInput!): Return! "REFUND a received Return. method=original_tender drives the PROCESSOR walk: the order's INTEGRATED payments (captured|succeeded) refund LIFO through the StripePort — each attempt record-first (a Refund child mints created, the port fires after, the ACK commits the NEGATIVE card Tender + the Order rollup + the settled flip in ONE transaction); over-capacity refuses CONFLICT/OVER_TENDERED (route the remainder via cash/store_credit); a processor refusal refuses PAYMENT/REFUND_FAILED (retryable — committed sibling refunds STAND and the retry converges on the remainder); an order with NO integrated payments keeps the ratified record-only arm. method=cash pays out of the OPEN drawer; store_credit records (issuance). Requires the doc CURRENT revision (OCC) + the unrestricted capability." refundReturn(input: RefundReturnInput!): Return! "OPEN a till session at a Register: ONE transaction — the doc + the one-live-per-register marker (a LIVE holder refuses CONFLICT/IDENTITY_TAKEN naming the open session; a TERMINAL holder is taken over) + one float_in entry per positive-float currency + the drawerTotals cache birth. The Register must be ACTIVE (tenant-scoped); openedBy stamps from the principal. Requires the unrestricted capability." openTillSession(input: OpenTillSessionInput!): TillSession! "CLOSE a counting till session: per currency overShort = counted − expected (the drawerTotals cache); each non-zero posts a count_adjust entry (the post-close ledger sum == counted BY CONSTRUCTION); counted/overShort/closedAt stamp in the SAME transaction. The over_short_threshold → CONFLICT/OVER_SHORT_REVIEW form is -dormant (declared; the review path =). Requires the doc CURRENT revision (OCC) + the unrestricted capability." closeTillSession(input: CloseTillSessionInput!): TillSession! "RECORD one MANUAL drawer entry against an OPEN till session: the entry + the drawerTotals cache stamp land in ONE transaction under the session's OCC (concurrent records serialize CONFLICT/REVISION_STALE, retryable); an entry driving its currency's total negative stamps overdrawn + is evented. Requires the unrestricted capability." recordCashEntry(input: RecordCashEntryInput!): CashEntry! "APPLY one tender to a PLACED order: cash — roundedDue per the CASH_ROUNDING increments (the sale total NEVER changes); (collected − tip) ≥ roundedDue ⇒ SETTLING (applied = the EXACT remainder, change = collected − tip − roundedDue, the ± roundingDelta stamps); else PARTIAL (the deposit lane). external_card — the RECORDED capture (≤ the remainder EXACTLY; no drawer). card — the INTEGRATED lane. The cash/recorded lanes stay ONE transaction: the tender row + the Order tenderedNetMinor/tipTotalMinor/paymentState stamp (OCC) + for cash the cash_sale (+ change_given) entries + the drawerTotals stamp. A fully-tendered order refuses CONFLICT/OVER_TENDERED. Requires the unrestricted capability." applyTender(input: ApplyTenderInput!): Tender! "REFUND part of a PLACED order's tendered deposit: a NEGATIVE tender row + for cash the cash_refund drawer lane + both OCC stamps in ONE transaction; cap = the net tendered (CONFLICT/OVER_TENDERED); reason REQUIRED. cancelOrder refuses CONFLICT/TENDERED while net tendered > 0 — refund-then-cancel. Requires the unrestricted capability." refundTender(input: RefundTenderInput!): Tender! "The POS-with-receipt return collapse: ONE call walks requested→approved→received→refunded with the cash refund REACHING the drawer. The return.approve gate evaluates UP FRONT — a below-pass tier refuses AUTHZ/APPROVAL_REQUIRED and uses the op-by-op walk (the approval fingerprint needs a pre-existing target). Realized as the op-by-op steps composed — each transaction atomic; a mid-walk failure PARKS the Return at a resumable state (posReturnParked in the error detail names it). Requires the unrestricted capability." posReturn(input: PosReturnInput!): Return! "Open the drawer WITHOUT a sale: moves NO money; the write IS the audit trail (noSaleCount/lastNoSaleAt under OCC — the stream events it; the fraud feed reads it); reason REQUIRED; the session must be open. Requires the unrestricted capability." noSale(input: NoSaleInput!): TillSession! "START one card-present payment on the caller's PAIRED READER: REQUIRES the composite POS session (the x-at-device-session facet — the reader resolves from THE DEVICE, never caller-named: ACTIVE + register-paired, exactly ONE active registered card reader; the device's org chain must equal the order's selling org). The selling org must hold a CONNECTED chargeable account (NO platform arm — the direct-charge money-destination law; CONFLICT/REF_STATE otherwise). Record-first: the Payment mints created with methodRef = the reader's readerRef, THEN the processor intent hands to the reader and this op RETURNS — the customer taps; the payment_intent.amount_capturable_updated truth commits the Tender row + the Order rollup + the created→authorized flip in ONE transaction (the webhook SoT; a fully-delivered order then CAPTURES — the seam), and a reader DECLINE lands the attempt failed via payment_intent.payment_failed. Poll the payment record for the outcome (the CQRS shape). A reader refusal (busy/offline — NO card presented) refuses PAYMENT/READER_UNAVAILABLE with the attempt recorded failed (retryable — record-per-attempt). Requires the unrestricted capability. Template class (the applyTender ring plane — hand-derived v32)." processReaderPayment(input: ProcessReaderPaymentInput!): Payment! "REFUSES unless the new coupon settles applied: NOT_FOUND/COUPON (unknown/doomed/malformed code) · CONFLICT/REF_STATE (a staged holder) · CONFLICT/COUPON_EXPIRED (outside [startAt, endAt)) · CONFLICT/COUPON_EXHAUSTED (the total-use cap) · VALIDATION/COUPON_INELIGIBLE (scope/min-spend miss, nothing to reduce, or the trigger's promotion did not fire). ONE coupon per order — the strict default (VALIDATION/INVALID; the widening is unbuilt). Any other state refuses CONFLICT/REF_STATE. Requires the unrestricted capability + the record's CURRENT revision." applyOrderCoupon(orderId: ID!, revision: ID!, code: String!): Order! "DETACH an attached coupon from an order while open, or while a draft/quote is draft/sent: the remaining engines re-evaluate and the order re-stamps in ONE revision (the LAST removal drops the couponIds slot — the invoiceIds delete-key law). A non-attached id refuses NOT_FOUND/COUPON; any other state refuses CONFLICT/REF_STATE. Requires the unrestricted capability + the record's CURRENT revision." removeOrderCoupon(orderId: ID!, revision: ID!, couponId: ID!): Order! "ACTIVATE staged instrument stock DIRECTLY: the flip + the issue entry + the balance land in ONE transaction. amountMinor ≥ 1 (an instrument never activates empty — VALIDATION/INVALID); reason REQUIRED (money is born). Requires the unrestricted capability + the record's CURRENT revision." activateStoredValueInstrument(input: ActivateStoredValueInstrumentInput!): StoredValueInstrument! "ADJUST an instrument balance — the privileged manual correction: a SIGNED non-zero delta + the REQUIRED reason post ONE adjust entry + the CONDITIONED cached-balance apply (below-zero refuses CONFLICT/INSUFFICIENT_BALANCE naming the live figures). active|depleted targets only (CONFLICT/REF_STATE otherwise); a positive adjust on depleted RE-OPENS it (system:refund_credit); a draw landing ZERO on a non-reloadable flips depleted in the SAME transaction. Requires the unrestricted capability + the record's CURRENT revision." adjustStoredValueInstrument(instrumentId: ID!, revision: ID!, amountMinor: Int!, reason: String!): StoredValueInstrument! "Attach a LoyaltyMember to an OPEN SALE. redeemPoints ABSENT = attach-for-EARN-only; PRESENT = the redemption request the position-4 evaluation converts to source=loyalty PRE-TAX LINE entries. Gates in order: member NOT_FOUND/CONSTRUCT → program org-enablement + order⟺program currency → the verdict map (CONFLICT/REF_STATE on a dead program/member/window · CONFLICT/INSUFFICIENT_POINTS naming live figures · VALIDATION/INVALID on zero-value / exceeds-available naming figures — never silently take less). The cart money re-stamps in the SAME revision; PLACE re-validates FRESH (commit truth). Requires the unrestricted capability + the record's CURRENT revision." applyOrderLoyalty(orderId: ID!, revision: ID!, memberId: ID!, redeemPoints: Int): Order! "Detach the loyalty block from an OPEN order: re-evaluate + re-stamp (the loyalty entries vanish with their context); the removal DROPS the loyalty attribute (the couponIds delete-key law — HARD-1, so no member argument exists). No block attached refuses NOT_FOUND/CONSTRUCT. Requires the unrestricted capability + the record's CURRENT revision." removeOrderLoyalty(orderId: ID!, revision: ID!): Order! "ADJUST a member's points — the privileged manual correction: a SIGNED non-zero delta + the REQUIRED reason post ONE adjust entry + the CONDITIONED cached-balance apply (below-zero refuses CONFLICT/INSUFFICIENT_POINTS naming live figures; the ceiling refuses VALIDATION/INVALID). active|inactive targets only (CONFLICT/REF_STATE on doomed). Requires the unrestricted capability + the record's CURRENT revision." adjustLoyaltyPoints(memberId: ID!, revision: ID!, points: Int!, reason: String!): LoyaltyMember! "Attach an employee discount to an OPEN order of ANY type. percentPpm is caller-supplied v1 ((0, 1000000] — policy rates/caps are the named tail). Gates in order: user NOT_FOUND/CONSTRUCT → a non-ACTIVE user CONFLICT/REF_STATE → THE discount.apply AUTHORITY ARM. The cart money re-stamps in the SAME revision with source=employee LINE entries at position 5 (the LAST pre-tax reduction); PLACE re-validates the User FRESH (commit truth). Requires the unrestricted capability + the record's CURRENT revision." applyOrderEmployeeDiscount(orderId: ID!, revision: ID!, userId: ID!, percentPpm: Int!): Order! "Detach the employee discount from an OPEN order: re-evaluate + re-stamp (the employee entries vanish with their context; a loyalty earn re-derives UP on the restored bases); the removal DROPS the employee attribute (the couponIds delete-key law — HARD-1, so no user argument exists). No block attached refuses NOT_FOUND/CONSTRUCT. Requires the unrestricted capability + the record's CURRENT revision." removeOrderEmployeeDiscount(orderId: ID!, revision: ID!): Order! "SCHEDULE a draft MarkdownPlan: (1) VALIDATE pure-reads — every step future · the scope resolves via the engine to ACTIVE products/variants × the plan's LF set → the InventoryItems THAT EXIST (ZERO resolved = VALIDATION/INVALID — a plan that moves nothing is an authoring error) · the ≤250-items/≤500-writes caps (VALIDATION/INVALID naming the figures) · per II: the schedule currency must EQUAL the plan currency (the law) · base₀ = the ACTIVE record covering step-1's startAt (none = VALIDATION/INVALID — a markdown MOVES an existing price) · the ladder (each PRIOR RESULT, half-away rounding) must stay > 0 · a forward splice check — ANY overlap refuses CONFLICT/PRICE_WINDOW_OVERLAP naming {II, blockers}, ALL-OR-NOTHING. (2) WRITE every future-dated SalePrice through the EXISTING per-record create (splice-gated, evented, plan/step-stamped; the FIRST window per II TRIMS the covering standing record). (3) FLIP draft→scheduled (OCC) stamping nextDueAt + resolvedInventoryItemIds. IDEMPOTENT-RESUME: a mid-flight fault refuses naming progress with the plan still draft — a re-run SKIPS its own already-written step-prefix and retries the flip. Requires the unrestricted capability + the record's CURRENT revision." scheduleMarkdownPlan(input: ScheduleMarkdownPlanInput!): MarkdownPlan! "CANCEL a MarkdownPlan from draft|scheduled|active: dooms every plan-stamped SalePrice with startAt STRICTLY FUTURE (BY DATE — effective/past windows are PERMANENT price history, skipped, never attempted), then flips → cancelled (OCC; the terminal status disarms the scheduler lane). The step-1 TRIM is NOT restored (no-silent-unwind — schedule a new window to re-price). A fault mid-doom leaves an un-cancelled plan with some doomed records — re-run to complete (a doomed record blocks nothing). Requires the unrestricted capability + the record's CURRENT revision." cancelMarkdownPlan(input: CancelMarkdownPlanInput!): MarkdownPlan! "PAY DOWN a house account: ONE payment AREntry + the CONDITIONED balance decrement + THE FIFO FRONTIER ADVANCE land in ONE transaction (strictly oldest-first over open charges; ledger entries stay 100% immutable — the frontier pair moves on the MASTER). amountMinor ≤ arBalanceMinor else CONFLICT/INSUFFICIENT_AR_BALANCE naming live figures (AR never negative; prepayment/credit balances = the named deferral). NO allocations array (deterministic law + the event lake = the audit trail). Requires the unrestricted capability." arPay(input: ArPayInput!): OrgCustomer! "WRITE OFF bad debt: ONE writeoff AREntry (REQUIRED reason) + the same conditioned decrement/frontier machinery; ≤ the balance else CONFLICT/INSUFFICIENT_AR_BALANCE. Descriptor-gated to the management templates (the voidInvoice class — v17). Requires the unrestricted capability." arWriteoff(input: ArWriteoffInput!): OrgCustomer! "SETTLE an ISSUED CreditNote against the customer's AR: gates the note issued (closed/voided refuse CONFLICT/IMMUTABLE) + the note-order's (org × cc) ACTIVE enablement + the currency law + |totalDeltaMinor| ≤ arBalanceMinor (CONFLICT/INSUFFICIENT_AR_BALANCE) → ONE transaction {the credit_memo AREntry (ref creditNoteId) + the conditioned decrement/frontier + settlementState unsettled→settled + the FSM flip issued→closed via system:delta_settled} — the FIRST corrective-note close producer. The MONEY-settle lane stays the NAMED deferral (the refund↔note linkage ruling). Requires the unrestricted capability + the record's CURRENT revision." settleCreditNoteToAr(input: SettleCreditNoteToArInput!): CreditNote! "SETTLE an ISSUED DebitNote against the customer's AR: posts the charge AREntry (= totalDeltaMinor; dueAt per the enablement's NET terms — cod/prepaid/undeclared refuse CONFLICT/REF_STATE, a DN needs a due date to ride AR) + the SAME-transaction settled+closed flip. ⚠ NOT limit-gated (the disclosed lean — a correction documents debt that already exists; only the TENDER extends new credit). Requires the unrestricted capability + the record's CURRENT revision." settleDebitNoteToAr(input: SettleDebitNoteToArInput!): DebitNote! "REORDER: mint a NEW sale Order BORN OPEN (a cart to review — placing runs every place law, incl. the orderMinimum gate) from a sale-profile NON-DOOMED source. CLONES: the variant lines as {variantId, quantity} (fulfillmentMethod re-DEFAULTS per the create path) + the customer block VERBATIM (re-validated by the create gates — a dead cc/enablement/buyer refuses NAMED). Does NOT clone: captured prices (RE-CAPTURED FRESH by the live ContractPrice → PriceList → SalePrice resolution — price history is fact), line/order discounts, coupon/loyalty/employee attaches, agent attributions, the exemption cert, every fulfillment/tender stamp. open_item lines refuse VALIDATION/UNSUPPORTED naming the lineNos (no catalog identity to re-price; partial-clone = the surface deferral); stored-value issuance lines the SAME class (an instrument sale is its own act). A dead/retired variant refuses NAMED by the existing line gates (whole-refusal v1). The mint stamps reorderOfOrderId = the source id. Requires the unrestricted capability." reorderOrder(input: ReorderOrderInput!): Order! "COPY-TO-CUSTOMIZE a canned role template: mints an ORDINARY editable group Role carrying the template's compiled descriptors + the PORT-stamped provenance (templateKey/templateVersion — never caller-suppliable) + the authorityTier. Requires the unrestricted capability." copyCannedRole(input: CopyCannedRoleInput!): Role! "MINT an ApprovalRequest: ONE transaction — the doc + the (target, action) fingerprint marker (a LIVE-unexpired holder refuses CONFLICT/REFERENCED naming it). requiredTier derives from the canned grants; expiresAt = now + 900s (a touch past it refuses CONFLICT/EXPIRED and lazily expires the request). On approval the REQUESTER retries the identical gated call — the retry consumes the approval by fingerprint (single-use). Requires the unrestricted capability." requestApproval(input: RequestApprovalInput!): ApprovalRequest! "SHIP a packed Fulfillment: packed→shipped→FULFILLED in ONE call (ship = delivered, the operator ruling — both edges evented, one transaction): the claimed lines relieve through the sell-relief lane (partial quantities; the ecom reserve releases; COGS at the current WMA; the composed action budget pre-gates ≤ 100), the ORDER line fulfilledQty stamps + both delivery rollups recompute, and a paid-and-delivered order COMPLETES (system:fully_paid_and_delivered). The capture seam is DECLARED-dormant. Requires the unrestricted capability." shipFulfillment(input: ShipFulfillmentInput!): Fulfillment! "SUBMIT dispute evidence: the processor submission fires FIRST (evidence[uncategorized_text] + submit=true — never inside a transaction; a processor refusal is CONFLICT/RECONCILE, retryable, nothing changed), then the flip stamps evidenceText WITH it (the presence law). Carries authority:manage_dispute. Requires the doc CURRENT revision (OCC) + the unrestricted capability." submitEvidenceDispute(input: SubmitEvidenceDisputeInput!): Dispute! "STAFF: mint (or ROTATE) the ONE outstanding show-once invite token for an ACTIVE collaborator: the plaintext token rides THIS result ONCE; a re-issue makes the prior token STALE (the pointer-currency law — the single live slot); a non-active collaborator refuses CONFLICT/REF_STATE. ⚠ NO staff password-set lane exists on this plane EVER — this rotation IS the recovery lane (the merchant never knows the secret). Template class; requires the unrestricted capability." issueCollaboratorInvite(collaboratorId: ID!): CollaboratorInviteMint! "Reserved for the platform; not available to API keys." acceptCollaboratorInvite(token: String!, password: String!): Boolean! "Reserved for the platform; not available to API keys." collaboratorLogin(orgId: ID!, email: String!, password: String!): CollaboratorAuthResult! "Reserved for the platform; not available to API keys." collaboratorLogout: Boolean! "Reserved for the platform; not available to API keys." changeMyCollaboratorPassword(currentPassword: String!, newPassword: String!): Boolean! "Reserved for the platform; not available to API keys." revokeMyCollaboratorSessions: Int! "STAFF: the revoke-ALL kill-switch pointed at a collaborator; revokes every currently-active session of the named collaborator, returns the count. Template class; requires the unrestricted capability." revokeCollaboratorSessions(collaboratorId: ID!): Int! "Reserved for the platform; not available to API keys." consumerRegister(orgId: ID!, input: NewConsumerInput!, password: String!): ConsumerAuthResult! "Reserved for the platform; not available to API keys." consumerLogin(orgId: ID!, email: String!, password: String!): ConsumerAuthResult! "Reserved for the platform; not available to API keys." consumerLogout: Boolean! "Reserved for the platform; not available to API keys." updateMyConsumer(input: EditConsumerInput!): Consumer! "Reserved for the platform; not available to API keys." changeMyConsumerPassword(currentPassword: String!, newPassword: String!): Boolean! "Reserved for the platform; not available to API keys." revokeMyConsumerSessions: Int! "STAFF: the revoke-ALL kill-switch pointed at a consumer; revokes every currently-active session of the named consumer, returns the count. Template class (identity & access admin — the high-authority row); requires the unrestricted capability." revokeConsumerSessions(consumerId: ID!): Int! "STAFF: set a consumer's password credential DIRECTLY: writes a NEW argon2id credential; arms self-service on a staff-created profile; REFUSED on a doomed (de-identified) consumer. Existing sessions stay live — pair with revokeConsumerSessions for a takeover response. Template class; requires the unrestricted capability." resetConsumerPassword(consumerId: ID!, newPassword: String!): Boolean! "COPY-TO-CUSTOMIZE a canned consent purpose: mints an ORDINARY editable group ConsentPurpose carrying the template's code + consentModel + the PORT-stamped provenance (templateKey/templateVersion — never caller-suppliable). The code marker reserves in the create transaction (a NON-DOOMED holder refuses CONFLICT/IDENTITY_TAKEN — copy the template ONCE per group, or re-code the copy). Requires the unrestricted capability. Template class (privacy & compliance — hand-derived v20)." copyCannedConsentPurpose(input: CopyCannedConsentPurposeInput!): ConsentPurpose! "STAFF: record a GRANT decision for a NAMED consumer: NO record → DUAL-BIRTH born granted (the PERMANENT pair marker + the FIRST-decide everReferenced stamp ride the ONE transaction) · withdrawn → the evented transition (capture context REFRESHED) · already granted → a capture-context REVISION (re-consent under a new policyVersion — never an FSM self-loop). Gates: purpose ACTIVE + consumer NOT doomed (each CONFLICT/REF_STATE naming it; a SUSPENDED consumer stays LEGAL — the subject's right). The create race self-cures via the marker. Requires the unrestricted capability. Template class (capture-at-source — hand-derived v20)." grantConsent(input: ConsentDecisionInput!): ConsentRecord! "STAFF: record a WITHDRAW decision for a NAMED consumer: NO record → dual-birth born withdrawn (PROOF-OF-REFUSAL — prevents re-asking, ruling 4) · granted → the evented transition · already withdrawn → the revision. The same gates + routing verbatim. Template class (classifies WITH the grant — v20)." withdrawConsent(input: ConsentDecisionInput!): ConsentRecord! "Reserved for the platform; not available to API keys." grantMyConsent(input: MyConsentDecisionInput!): ConsentRecord! "Reserved for the platform; not available to API keys." withdrawMyConsent(input: MyConsentDecisionInput!): ConsentRecord! "STAFF: append ONE message to a case's thread: visibility is the author's CHOICE (an internal_note NEVER crosses the consumer face — ruling); the acting User stamps as the author. A terminal (closed/cancelled) case refuses CONFLICT/IMMUTABLE — frozen history. The append is EVENTED (at.cs.case_message.append.ok.v1 rides the record-change lake). Requires the unrestricted capability. Template class (the capture tier — hand-derived v21)." addCaseMessage(input: NewCaseMessageInput!): CaseMessage! "Reserved for the platform; not available to API keys." openMyCase(input: OpenMyCaseInput!): CsCase! "Reserved for the platform; not available to API keys." addMyCaseMessage(input: NewMyCaseMessageInput!): CaseMessage! "Reserved for the platform; not available to API keys." requestMyReturn(input: RequestMyReturnInput!): Return! "STAFF: add ONE item to an ACTIVE registry: the (registry × variant) marker mints in the SAME transaction (a LIVE holder refuses CONFLICT/IDENTITY_TAKEN naming it; a DOOMED holder is TAKEN OVER — re-add after remove, ruling); the ACTIVE-items ceiling (200) gates; the variant live-gates. A non-ACTIVE registry refuses CONFLICT/REF_STATE (ruling). Requires the unrestricted capability. Template class (hand-derived v22)." addRegistryItem(input: NewRegistryItemInput!): RegistryItem! "STAFF: edit ONE item row (desiredQty/priority/note — MUTABLE under the row's OCC): variantId never moves (the membership identity — remove + re-add). The registry must be ACTIVE (ruling); a doomed row refuses CONFLICT/IMMUTABLE. Requires the unrestricted capability. Template class (hand-derived v22)." updateRegistryItem(input: EditRegistryItemInput!): RegistryItem! "STAFF: remove ONE item (= the TWO_STATE doom, history preserved): the row flips active → doomed through the runner (at.customer.registry_item.doom.ok.v1); the marker STAYS with the doomed holder for takeover (ruling). The registry must be ACTIVE (ruling). Requires the unrestricted capability. Template class (hand-derived v22)." removeRegistryItem(registryId: ID!, itemId: ID!, reason: String): RegistryItem! "STAFF: record ONE purchase fact against a registry item: IMMUTABLE once recorded (the TENTH LEDGER_FACT); the registry must be NON-DOOMED (active/closed/expired ALL record — ruling); the item ACTIVE; the order in-tenant + non-doomed; ⚠ the named line's variant MUST equal the item's variant (the fact names its line); OVER-fulfillment records LEGALLY (remaining floors 0). Requires the unrestricted capability. Template class (the capture tier — hand-derived v22)." recordRegistryFulfillment(input: RecordRegistryFulfillmentInput!): RegistryFulfillment! "Reserved for the platform; not available to API keys." createMyGiftRegistry(input: CreateMyGiftRegistryInput!): GiftRegistry! "Reserved for the platform; not available to API keys." updateMyGiftRegistry(id: ID!, revision: ID!, input: EditGiftRegistryInput!): GiftRegistry! "Reserved for the platform; not available to API keys." closeMyGiftRegistry(id: ID!, revision: ID!, reason: String): GiftRegistry! "Reserved for the platform; not available to API keys." doomMyGiftRegistry(id: ID!, revision: ID!, reason: String): GiftRegistry! "Reserved for the platform; not available to API keys." addMyRegistryItem(input: NewRegistryItemInput!): RegistryItem! "Reserved for the platform; not available to API keys." updateMyRegistryItem(input: EditRegistryItemInput!): RegistryItem! "Reserved for the platform; not available to API keys." removeMyRegistryItem(registryId: ID!, itemId: ID!, reason: String): RegistryItem! "Reserved for the platform; not available to API keys." submitMyReview(input: SubmitMyReviewInput!): Review! "Reserved for the platform; not available to API keys." updateMyReview(input: EditMyReviewInput!): Review! "Reserved for the platform; not available to API keys." grantTokens(input: GrantTokensInput!): TokenGrantResult! "Reserved for the platform; not available to API keys." adjustTokens(input: AdjustTokensInput!): TokenGrantResult! "Reserved for the platform; not available to API keys." transferTokens(input: TransferTokensInput!): TokenTransferResult! "Attach ONE stored off-session payment method to the caller-group's wallet: the wallet's platform Stripe Customer mints LAZILY (idempotent — a retry converges on the SAME Customer), the method attaches, then ONE OCC write stamps the server-only refs + the readable {brand, last4, attachedAt} facts (the refs NEVER cross the wire — read billingMethod instead). A wallet already carrying a method refuses CONFLICT/REF_STATE (detach first; replacement is the explicit auditable two-step). ⚠ Custody ARMS the charger's auto-top-off + base-fee lanes (the merchant consents to off-session charges by storing the method). Requires the unrestricted capability. Template class A16_BILLING (hand-derived v24)." attachTokenAccountBillingMethod(input: AttachTokenAccountBillingMethodInput!): TokenAccount! "Detach the caller-group wallet's stored method: the processor detach fires FIRST, then the method ref + the facts trio REMOVE together (absent IS the cleared state; the Customer anchor stays for a future re-attach). Custody DISARMS — auto-top-off stops firing (STOP is safe: the exhaustion ladder + manual purchases stand) and a production group's base fee reads uncollectable. No stored method refuses CONFLICT/REF_STATE. ⚠: refuses while a BACKUP method stands (a primary-less backup is incoherent — detach the backup first). Requires the unrestricted capability. Template class A16_BILLING (hand-derived v24)." detachTokenAccountBillingMethod: TokenAccount! "Attach a BACKUP off-session method to the caller-group's wallet. The charger's auto-top-off falls back to it when the PRIMARY declines (a fresh purchase per intent — never a double charge). Refuses without a primary (CONFLICT/REF_STATE — a backup exists only as its fallback) and over a standing backup. Requires the unrestricted capability. Template class A16_BILLING (the custody-pair class)." attachTokenAccountBackupBillingMethod(input: AttachTokenAccountBillingMethodInput!): TokenAccount! "Detach the caller-group wallet's BACKUP method: the processor detach fires FIRST, then the backup ref + facts trio REMOVE together; the primary + the Customer stand untouched. Top-offs lose their fallback — a declined primary then stops the auto-buy (on the cards-failing lane). No stored backup refuses CONFLICT/REF_STATE. Requires the unrestricted capability. Template class A16_BILLING (the custody-pair class)." detachTokenAccountBackupBillingMethod: TokenAccount! "Buy kernels NOW with the stored card: mints a TokenPurchase charged OFF-SESSION to the stored method (primary → backup ladder, the charger's fire mechanics; the SAME webhook settles the balance credit). ⚠ NOT budget-capped BY DESIGN — the day/month caps fence AUTO spend; an explicit press is its own authorization. The amount rides the createTokenPurchase bounds and must clear the volume-tier floor (below refuses VALIDATION). The wallet must be ACTIVE with custody armed (no stored method refuses CONFLICT/REF_STATE — use createTokenPurchase for a client-confirmed buy instead). Requires the unrestricted capability. Template class A16_BILLING (the createTokenPurchase class)." purchaseTokensNow(input: NewTokenPurchaseInput!): TokenPurchase! "Buy the quarterly handholding plan: classes the trailing quarter's usage, charges the tier OFF-SESSION to the stored card (the purchaseTokensNow ladder), and arms the plan — it serves HUMAN incidents 72 h after purchase (the CAA activation wait; the $150 per-incident lane stays open meanwhile). The quarter covers the purchase month + 2 (renewals are AUTOMATIC — the billing engine collects each next quarter until you cancel). Already covered refuses CONFLICT (nothing to buy); a canceled-but-covered plan RESUMES instead (the cancel clears, nothing mints, no new wait); a lapsed/never plan mints + the wait re-arms. Wallet + stored method required. Requires the unrestricted capability. Template class A16_BILLING (hand-derived v93)." purchaseSupportPlan: SupportPlanReport! "Stop the handholding plan's renewals: paid coverage serves through its quarter (coveredThroughMonth), then the plan lapses; re-purchasing later re-arms the 72 h wait. No standing plan / already canceled refuses CONFLICT. Requires the unrestricted capability. Template class A16_BILLING (hand-derived v93)." cancelSupportPlan: SupportPlanReport! "Ask AlmondTill to move named kernel blocks to another group WHOLE. Eligible blocks: never-opened, unfrozen stock (approved | transfer_denied) settled ≥ 90 days ago and never moved before (one transfer per block, forever). ⚠ THE ASK FREEZES the blocks at once — they cannot be consumed until AlmondTill approves or denies (freezing most of your stock can starve the wallet; the answer names each block's state). An ineligible block refuses with why; the destination must be another group with a live wallet. Requires the unrestricted capability. Template class A16_BILLING (hand-derived v94)." requestKernelBlockTransfer(input: RequestKernelBlockTransferInput!): [KernelBlock!]! "Claim your group's ONE referral code: a generated code owned by your group, carrying the two-sided standard (the referred business gets 50% off its base fee for 3 cycles; you earn on their collected fees and their first-year kernel consumption once AlmondTill approves each referral). Requires APPROVED affiliate standing (AlmondTill grants it — ask us; a default waiting period applies from your signup). One code per group, forever — a second claim refuses naming the standing code. Requires the unrestricted capability. Template class A16_BILLING (hand-derived v94)." claimReferralCode: ClaimedReferralCode! "Reserved for the platform; not available to API keys." submitOnboardingSignup(input: OnboardingSignupPayloadInput!): SubmitOnboardingSignupResult! "Reserved for the platform; not available to API keys." redeemOnboardingEmailVerification(token: String!): RedeemOnboardingEmailVerificationResult! "Reserved for the platform; not available to API keys." resendOnboardingEmailVerification(input: ResendOnboardingEmailVerificationInput!): ResendOnboardingEmailVerificationResult! "Reserved for the platform; not available to API keys." requestPasswordReset(email: String!): RequestPasswordResetResult! "Reserved for the platform; not available to API keys." completePasswordReset(token: String!, newPassword: String!): CompletePasswordResetResult! "Reserved for the platform; not available to API keys." approveChangeRequest(id: ID!, reason: String): ChangeRequest! "Reserved for the platform; not available to API keys." rejectChangeRequest(id: ID!, reason: String!): ChangeRequest! "Reserved for the platform; not available to API keys." requestChangeRequestInfo(id: ID!, note: String!): ChangeRequest! "Reserved for the platform; not available to API keys." resubmitChangeRequest(id: ID!, input: OnboardingSignupPayloadInput!): ChangeRequest! "Reserved for the platform; not available to API keys." cancelChangeRequest(id: ID!, reason: String): ChangeRequest! "Reserved for the platform; not available to API keys." realizeChangeRequest(id: ID!, classification: String, code: String): ChangeRequest! "File ONE management ChangeRequest against an org in the caller's OWN group: ONE txn = the group-parented request (born submitted) + the review-queue row + the pending-(type×org) reservation (a duplicate live request refuses the FIXED sentence naming nothing about the holder; released at EVERY terminal). The target org gates at submit: in-group (cross-tenant reads NOT_FOUND — the opaque law) · non-doomed · in the bound edge's from-state (CONFLICT/REF_STATE naming the edge)." submitChangeRequest(requestType: String!, input: OrganizationLifecyclePayloadInput!): ChangeRequest! "Cancel the caller group's OWN live request." cancelMyChangeRequest(id: ID!, reason: String): ChangeRequest! "Resubmit the caller group's OWN bounced request. ⚠ the org-immutability rule: the organization is the pending-pair reservation coordinate — a different org is a NEW request (cancel this one first)." resubmitMyChangeRequest(id: ID!, input: OrganizationLifecyclePayloadInput!): ChangeRequest! "Reserved for the platform; not available to API keys." createReferralCode(input: NewReferralCodeInput!): ReferralCode! "Reserved for the platform; not available to API keys." disableReferralCode(code: String!): ReferralCode! "Append ONE immutable note to ANY same-tenant construct: the target gates existence + same-rootId (its type stamps onto the row); parentNoteId threads ONE level (a reply-to-a-reply refuses naming the root); links ≤8 scheme-fenced; attachmentIds bind the caller's own PRIOR upload-mints — the commit HeadObject-verifies each blob, composes the IMMUTABLE META, flips the pending tag, stamps the wallet counter, and mints the BLOBBOOK rows, ALL in ONE transaction. The acting User stamps as the author. Requires the unrestricted capability. Template class (universal staff work — hand-derived v29)." addNote(input: NewNoteInput!): Note! "Park a task until a chosen future moment: returnAt must be a FUTURE ISO-8601 instant (the setBookmarkPop grammar — a past/invalid instant refuses VALIDATION/INVALID naming it); the USER/TEAM inbox rows PRUNE in the same txn (parking means quiet — the REF row keeps it visible on its record); at returnAt the scheduled sweep fires the return AUTOMATICALLY (re-minting the inbox rows), or transitionTask op=unpostpone (“Return now”) pulls it back early. A re-park restamps returnAt. On a note-minted task the transition appends its narrative reply under the origin root (the law). Requires the unrestricted capability + the record's CURRENT revision. Template class (hand-derived v29)." postponeTask(id: ID!, revision: ID!, returnAt: String!, reason: String): Task! "React to ONE note: one mark per (you, emoji) — a duplicate refuses CONFLICT (remove it first); emoji ∈ the canned token set (thumbs_up, check, question, eyes, tada, warning, plus, heart — STRICT). The note must exist on the named target in your workspace. Answers the note's FRESH reaction groups. Requires authentication." reactToNote(targetConstructId: ID!, noteId: ID!, emoji: String!): [NoteReactionGroup!]! "Remove YOUR reaction: strict — removing a mark you never made refuses NOT_FOUND (never a silent no-op). Answers the note's FRESH reaction groups. Requires authentication." unreactToNote(targetConstructId: ID!, noteId: ID!, emoji: String!): [NoteReactionGroup!]! "Template class (hand-derived v29)." mintNoteAttachmentUpload(input: MintNoteAttachmentUploadInput!): NoteAttachmentUploadTicket! "Mint a short-TTL presigned DOWNLOAD for one note attachment: authz through the target-construct read; scanned-prefix blobs gate on the GuardDutyMalwareScanStatus tag (NO_THREATS_FOUND serves · tag-absent = scan-in-progress refuses politely · THREATS_FOUND refuses + the event · UNSUPPORTED/ACCESS_DENIED/FAILED refuse FAIL-CLOSED naming the status); unscanned-prefix blobs skip the gate (risky types never landed there — the routing). Template class (hand-derived v29)." mintNoteAttachmentDownload(input: MintNoteAttachmentDownloadInput!): NoteAttachmentDownloadTicket! "Mint a short-TTL presigned UPLOAD for one wizard material: gates BEFORE any byte moves — the MATERIAL registry row must resolve (ext AND declared MIME agree; the scan-free subset: pdf/md/txt/png/jpg/jpeg/gif/webp/csv — archives never mint here) · bytes ≤ 8388608 (8 MiB) · the group wallet must exist (billed custody). The object lands PRE-TAGGED pending=true (the 7-day lifecycle reaps never-confirmed orphans) with the sha256 checksum + the mint metadata (incl. the wizard word — the walk-scope binding) SIGNED IN. wizardType is the wizard's kind word (the fill lanes' type, 1..64). Requires authentication (user sessions). Template class (universal staff work)." mintWizardMaterialUpload(input: MintWizardMaterialUploadInput!): WizardMaterialUploadTicket! "Confirm one uploaded wizard material: HeadObject-verifies custody (pending · YOUR OWN mint · byte match), runs THE ONE AI REVIEW of the raw bytes (surface office.material_extract — metered at.ai.call.v1; images ride vision, documents ride file input), stores the bounded EXTRACTION ARTIFACT beside the blob in the material book + stamps the wallet storage counter, ONE transaction. Material ⟺ extraction: a keyless/failed review refuses INTEGRATION/UNAVAILABLE WHOLE and the pending lifecycle reaps the blob — no un-reviewed material is ever kept. Later suggestFormFill/explainWizardStep presses compose from the stored extraction by id — the raw content is read exactly once, here. Requires authentication (user sessions). Template class (universal staff work)." confirmWizardMaterial(id: ID!): WizardMaterial! "Write or REPLACE the whole plan on a DRAFT scratchpad: the ordered create steps (≤24; seq assigned by position server-side). Every step validates against the LIVE registry + wire schema RIGHT HERE — an invalid step is MARKED with the exact problem and kept as written, never silently repaired; a plan with marked steps can be reviewed (ready) but can never be approved. A step's input may cite an earlier step's created record with the literal string @step:. Bumps planRevision (the approval pin's subject). Refuses CONFLICT/REF_STATE outside draft (reopen first — the review hold freezes the plan). Requires authentication (user sessions) + the record's current revision. Template class (universal staff work)." setScratchpadPlan(id: ID!, revision: ID!, steps: [ScratchpadPlanStepInput!]!): Scratchpad! "Execute an APPROVED plan: flips approved|realization_failed → realizing, then runs each unrealized step IN ORDER through the ordinary create operations UNDER YOUR OWN session, capability, and every normal gate (the hardened-Aldric law — the spine holds no authority of its own; per-step atomicity: each create is its own transaction). Every born id stamps back onto its step (the idempotency key — a re-run RESUMES, skipping realized steps, and never creates twice); every born record's history narrates this scratchpad and step. A step refusal stamps the fault VERBATIM and lands realization_failed — retry here to resume, or abandon (records already born stay). A crash caught between a step's commit and its stamp refuses auto-resume (the ambiguity fence — no silent duplicate is ever minted). Refuses CONFLICT/REF_STATE when the plan revision drifted from the approved pin. Requires authentication (user sessions) + the record's current revision. Template class (universal staff work)." realizeScratchpad(id: ID!, revision: ID!, reason: String): Scratchpad! "Run the suggestions desk for ONE organization: every ACTIVE (non-parked) declared skill's detector runs over bounded live reads (low_stock = the buy suggester · stock_imbalance = the rebalance suggester · aging_approvals = the scratchpad review roster; deterministic — zero AI calls v1) and the desk reconciles — the per-skill schema rows ensure-mint, past-due open offers expire (the shared flip), and fresh findings mint AUTHORLESS under the evidence-set dedup law (an identical open twin skips; changed content supersedes + re-mints; a declined twin with identical content holds for the offer window — the learning signal; a TAKEN twin with identical content holds while its born scratchpad still lives — the walk is the reminder, a second take would fork the work). Bounded ≤32 mints/org/UTC-day + ≤64 open/org + ≤8 candidates/skill — EVERY clip and skip is counted in the result, and a faulting detector lands in skillFaults while the other skills still run (bulkheaded). The organization must be yours and ACTIVE. Requires authentication. Template class (universal staff work — the OFFER law gates what the refresher then sees)." refreshSuggestions(organizationId: ID!): RefreshSuggestionsResult! "TAKE a suggestion: mints a Scratchpad THROUGH THE LIVE SPINE — origin `suggestion`, parented to YOU, the caption carried, the WHY as the intent, and the drafted plan landed via the setScratchpadPlan validate/mark path VERBATIM (a step that no longer checks out arrives MARKED, never silently repaired; the standing diff preview shows it). The offer law gates the act (every drafted step must be runnable under YOUR OWN capability — AUTHZ/FORBIDDEN naming the steps otherwise; preview ≡ enforcement) and your ≤16 open-scratchpad bound applies. The suggestion flips open→taken stamping takenScratchpadId in the SAME write; a lost race compensates (the fresh scratchpad abandons, reason narrated) and surfaces CONFLICT. A past-expiry open refuses CONFLICT/EXPIRED, lazily expiring on the touch. Returns the born Scratchpad — approve and realize it under your own gates (the hardened-Aldric law). Requires authentication (user sessions) + the record's current revision. Template class." takeSuggestion(input: TakeSuggestionInput!): Scratchpad! "Ask Aldric ONE question in a Consultation: appends your question, composes the STORED summary + the last 12 turns verbatim + your attached materials' STORED extractions (EXTRACT-THEN-COMPOSE — mint/confirm them with wizardType 'consultation' first; only YOUR OWN confirmed materials compose), asks the platform-keyed model, and appends the reply. When the un-summarized tail outgrows the window, the older turns FOLD into the stored summary FIRST (its own metered call — the memory is visible on the record, never hidden model state). A drafted plan in the reply is validated against the LIVE registry + wire schema as it lands — invalid steps arrive MARKED, never repaired; nothing real is created by asking (takeConsultationPlan mints the walk). Refuses INTEGRATION/UNAVAILABLE keyless · RATE_LIMIT/THROTTLED past the 30/hour allowance · CONFLICT/REF_STATE on a non-open consultation · the honest transcript-full refusal naming the follow-on cure. Every made call meters (at.ai.call.v1 — surfaces office.consultation + office.consultation_summary). Requires authentication (user sessions) + the record's current revision." askConsultation(input: AskConsultationInput!): AskConsultationResult! "TAKE the drafted plan from ONE of Aldric's replies: the plan RE-VALIDATES fresh through the setScratchpadPlan validate/mark path (stale steps arrive MARKED), the Scratchpad births parented to YOU (the birth cause narrates the consultation + turn), and the turn takes the SET-ONCE takenScratchpadId stamp — a second take refuses CONFLICT/REFERENCED naming the standing walk. Legal on open AND closed consultations (the drafted work outlives the conversation); your ≤16 open-scratchpad bound applies. Returns the born Scratchpad — review, approve, realize under your own gates (the hardened-Aldric law). Requires authentication (user sessions) + the record's current revision." takeConsultationPlan(id: ID!, revision: ID!, seq: Int!, reason: String): Scratchpad! "Bookmark ANY same-tenant construct: the target gates existence + same-rootId + non-doomed (its declared type IS the key namespace — the read proves it; a NOTE bookmarks by its OWN note id); teamId ABSENT = a personal bookmark, PRESENT = the team's shared set (the caller must be a MEMBER of that ACTIVE team; createdBy stamps the acting member — provenance). One row per (subject, target) — a duplicate refuses CONFLICT/BOOKMARK_EXISTS; the per-subject cap refuses CONFLICT/BOOKMARK_CAP. Requires authentication. Template class (universal staff work — the addNote kinship)." bookmarkConstruct(targetType: String!, targetId: ID!, teamId: ID): BookmarkRef! "Remove one bookmark: teamId ABSENT = my personal row, PRESENT = the team's row (membership-gated like bookmarkConstruct). An absent row refuses NOT_FOUND/BOOKMARK. Requires authentication. Template class (universal staff work)." unbookmarkConstruct(targetType: String!, targetId: ID!, teamId: ID): Boolean! "Pop one of YOUR bookmarks to the top of your feed. An absent row refuses NOT_FOUND/BOOKMARK — you boost what you subscribed. Requires authentication." boostBookmark(targetType: String!, targetId: ID!): BookmarkRef! "Schedule one of YOUR bookmarks to resurface. Requires authentication." setBookmarkPop(targetType: String!, targetId: ID!, popAt: String): BookmarkRef! "Pop a record to the top of YOUR TEAM's shared feed. Requires authentication." boostTeamBookmark(teamId: ID!, targetType: String!, targetId: ID!): BookmarkRef! "Schedule a record to resurface in YOUR TEAM's feed. Requires authentication." setTeamBookmarkPop(teamId: ID!, targetType: String!, targetId: ID!, popAt: String): BookmarkRef! "Mark one of YOUR bookmarks as a highlight. Requires authentication." highlightBookmark(targetType: String!, targetId: ID!): BookmarkRef! "Clear YOUR highlight. Requires authentication." unhighlightBookmark(targetType: String!, targetId: ID!): BookmarkRef! "Send ONE message to EXACTLY one recipient: a USER recipient must exist in-tenant + non-doomed (suspended still receives — a mailbox outlives a login); a TEAM recipient requires YOU to be a member of that ACTIVE team; the optional targetRef pair ('about this record') gates in-tenant + non-doomed. body ≤ 4096. The row lands in the recipient's current month bucket and persists (no deletion v1). Requires authentication. Template class (universal staff work — the addNote kinship)." sendMessage(toUserId: ID, toTeamId: ID, body: String!, targetType: String, targetId: ID): MessageRef! "Mark one of YOUR messages read. An absent row refuses NOT_FOUND/MESSAGE (team messages are unreachable here — no per-member team read state v1); an already-read message returns unchanged (FIRST read wins). Requires authentication." markMessageRead(messageId: ID!): MessageRef! "Mark one of YOUR notices read. An absent row refuses NOT_FOUND/NOTIFICATION; an already-read notice returns unchanged (FIRST read wins). Requires authentication." markNotificationRead(notificationId: ID!): NotificationRef! "Clear YOUR login session's Ask context: the assistant forgets this session's prior exchanges and the condensed memory; idempotent (a fresh thread answers the same zero meter). SELF by construction — no target argument exists. Requires authentication (user sessions)." resetAssistantContext: AssistantContextMeter! "Save ONE of your own app-private values at this organization. value ≤ 8 KB UTF-8; app/name ride the STRICT grammars ([a-z][a-z0-9-]{0,31} / [a-z0-9][a-z0-9._-]{0,63}). SELF-scoped BY CONSTRUCTION — no userId/orgId argument exists. Requires authentication." putMyAppData(app: String!, name: String!, value: String!): MyAppDataEntry! "Remove ONE of your own app-private values. Requires authentication." deleteMyAppData(app: String!, name: String!): Boolean! "Start — or re-open — the calling account's identity verification. Answers the hosted flow's short-lived url; a live attempt re-answers ITS fresh url (one attempt chain — only a canceled one re-mints). Refuses when the account holds no owner seat (CONFLICT/REF_STATE — the requirement attaches to ownership) and when already verified (CONFLICT/REF_STATE naming the forever law). SELF-scoped BY CONSTRUCTION; USER-plane only. Requires authentication." startIdentityVerification: IdentityVerificationStart! "Enroll a Device at an LF: the LF tenant-scoped + ACTIVE; an optional POS-class Register target may be declared (stamped at pairing completion; a pi_bridge refuses one — it serves the LF); returns the device + the single-use pairing code ONCE (TTL 15 min, hash-only at rest). Requires the unrestricted capability. Template class A3_DEVICE (manager+/owner G — hand-derived v30)." enrollDevice(input: EnrollDeviceInput!): DeviceEnrollment! "Reserved for the platform; not available to API keys." completePairingDevice(input: CompletePairingDeviceInput!): DevicePairingResult! "Mint a FRESH single-use pairing code for an existing Device: pending_pairing (the lost/expired first code) or active (pre-expiry rotation — the fresh exchange REPLACES the credential, the state never regresses); a suspended device refuses (the kill switch stays killed); the prior un-exchanged code invalidates. Template class A3_DEVICE (hand-derived v30)." reissueDevicePairingCode(input: ReissueDevicePairingCodeInput!): DeviceEnrollment! "Set/replace the 0..1 one-way Register binding on an ACTIVE POS-class Device: the Register tenant-scoped + ACTIVE; a pi_bridge refuses VALIDATION/INVALID; REFUSES CONFLICT/REFERENCED while the CURRENTLY-paired Register has a LIVE TillSession (the gate's intent — never orphan an open drawer). Template class A3_DEVICE (hand-derived v30)." pairDeviceToRegister(input: PairDeviceToRegisterInput!): Device! "Clear the Register binding (the pairDeviceToRegister twin — the same live-TillSession refusal). Template class A3_DEVICE (hand-derived v30)." unpairDevice(input: UnpairDeviceInput!): Device! "THE LOST-DEVICE KILL SWITCH: revoke EVERY live device session of one Device in one privileged act (compose with suspendDevice to also block re-exchange); reason REQUIRED — a kill switch never fires silently. Template class A3_DEVICE (hand-derived v30)." revokeAllDeviceSessions(input: RevokeAllDeviceSessionsInput!): RevokeAllDeviceSessionsResult! "Mint an ApiKey: OWNER-gated ENGINE-side (the minting actor's Account must hold group ownership LIVE — reach derives from those ownerships at every call); descriptors ride the grammar (≥1, deduped, IMMUTABLE); expiresAt ≤ 12 months (clock-gated); returns the key + the secret ONCE (hash-only at rest). Template class (integration config — Manager's hard-disallow correctly blocks the attempt at the descriptor layer; hand-derived v30)." mintApiKey(input: MintApiKeyInput!): ApiKeyMint! "Exchange an ApiKey secret for an API session: the key must be active AND reach-live (the minter's CURRENT ownerships — group + the named org); mints the 24 h-absolute no-idle API session and returns the bearer token ONCE. EVERY failure is uniform." exchangeApiKey(input: ExchangeApiKeyInput!): ApiKeyExchangeResult! "Reserved for the platform; not available to API keys." exchangeDeviceCredential(input: ExchangeDeviceCredentialInput!): DeviceSessionExchangeResult! "Reserved for the platform; not available to API keys." createTerminalConnectionToken: TerminalConnectionTokenResult! "Register an outbound webhook: OWNER-gated ENGINE-side (the caller's Account must hold group ownership LIVE); the target URL passes the egress law; every event name must be in the DERIVED deliverable universe; at most 10 ACTIVE subscriptions per group (the bounded fan-out law). Returns the subscription + the signing secret ONCE. Template class (integration config — hand-derived v71)." createWebhookSubscription(input: CreateWebhookSubscriptionInput!): WebhookSubscriptionMint! "Mint a FRESH signing secret for one webhook subscription: overwrites the credential-store row and returns the new secret ONCE, effective IMMEDIATELY (no dual-validity window — update your receiver first, then rotate); a doomed subscription refuses CONFLICT/IMMUTABLE. OWNER-gated ENGINE-side; OCC on the passed revision. Template class (hand-derived v71)." rotateWebhookSubscriptionSecret(id: ID!, revision: ID!, reason: String): WebhookSubscriptionSecretRotation! "Send ONE signed test delivery through the REAL webhook lane: ACTIVE subscriptions only (an inactive/suspended/doomed target refuses CONFLICT/FSM_TRANSITION_INVALID — the lane skips them by law); delivery is asynchronous at-least-once. OWNER-gated ENGINE-side. Template class (hand-derived v71)." pingWebhookSubscription(id: ID!): WebhookPingReceipt! "Mint a batch of UNIQUE SINGLE-USE child codes under one existing Coupon: ONE atomic transaction (48 codes max — bigger campaigns mint more batches); the codes are SERVER-GENERATED (-, the org-group code namespace — a collision refuses CONFLICT/COUPON_CODE_TAKEN, retry-able) and each unlocks the PARENT coupon's terms with ONE extra law: single use (the place transaction stamps it once-only). The coupon must be same-tenant + non-doomed (CONFLICT/REF_STATE). Requires the unrestricted capability. Template class (the coupon-authoring class — v79)." createCouponBatch(couponId: ID!, count: Int!, codePrefix: String!, caption: String): CouponBatchMint! "Add up to 48 Consumers to a STATIC segment in ONE transaction: every consumer must exist in YOUR tenant non-doomed; a DYNAMIC segment refuses (its membership derives — edit the predicate/exclusions and refreshSegment); the membership cap (100,000) refuses naming the figure; legal on active AND inactive segments (staging), never doomed. Requires the unrestricted capability. Template class (v80)." addSegmentMembers(segmentId: ID!, consumerIds: [ID!]!): AddSegmentMembersResult! "Remove up to 48 Consumers from a STATIC segment in ONE transaction. Requires the unrestricted capability. Template class (v80)." removeSegmentMembers(segmentId: ID!, consumerIds: [ID!]!): RemoveSegmentMembersResult! "Re-materialize a DYNAMIC segment's membership: a bounded probe sizes YOUR consumer universe first — at most 10,000 evaluates IN-REQUEST (the stored predicate, diffed against the member rows, adds/removes in bounded transactions, evaluatedAt stamped, refreshProblem cleared; answers queued: false + the arithmetic); past that the refresh is QUEUED (answers queued: true, arithmetic absent — the worker re-materializes up to 1,000,000 consumers; evaluatedAt moves on completion, refreshProblem words an over-cap outcome; a scheduled sweep also re-refreshes stale ACTIVE dynamics ~daily). Synchronous matches beyond the 100,000 membership cap refuse BEFORE any write; a static segment refuses (its membership moves via the member ops); legal on active AND inactive segments, never doomed. Not one atomic transaction — re-run heals an interrupted refresh. Requires the unrestricted capability. Template class (v89)." refreshSegment(id: ID!): RefreshSegmentResult! "Register a scheduled BI feed: OWNER-gated ENGINE-side (the caller's Account must hold group ownership LIVE); organizationId must be an in-group LIVE Organization (the per-org weld); dataset/cadence/format are canned vocabularies; at most 10 ACTIVE feeds per group. Template class (integration config — hand-derived v74)." createFeedSubscription(input: CreateFeedSubscriptionInput!): FeedSubscription! "Mark one ACTIVE feed due NOW. An inactive/suspended/doomed feed refuses CONFLICT/FSM_TRANSITION_INVALID. OWNER-gated ENGINE-side; OCC on the passed revision. Template class (hand-derived v74)." runFeedSubscriptionNow(id: ID!, revision: ID!, reason: String): FeedSubscription! "Mint ONE short-lived presigned download (TTL 300 s) for ONE of a feed's retained run objects. ZERO stored credentials — re-mint per pull under your own session. OWNER-gated ENGINE-side. Template class (hand-derived v74)." mintFeedRunDownload(feedSubscriptionId: ID!, key: String!): FeedRunDownloadTicket! "Decide ONE connector authorize request: the FULL params re-validate from scratch (the review is never trusted). APPROVE (orgId REQUIRED — an eligible org: ACTIVE + owned by you) mints a REAL ApiKey through the existing mintApiKey lane (the read-only integration descriptors AT APPROVE TIME; the 12-month ceiling; the caption carries the client) + the OAuth grant + the single-use PKCE-bound code, answering {redirectTo} with code+state+iss; DENY answers {redirectTo} with error=access_denied+state+iss (RFC 9207 — iss rides every response). Revoke later = the existing key doom. OWNER-gated engine-side (the mintApiKey posture VERBATIM). Template class (hand-derived v82)." approveConnectorAuthorization(decision: String!, orgId: ID, responseType: String!, clientId: String!, redirectUri: String!, codeChallenge: String!, codeChallengeMethod: String!, state: String, scope: String, resource: String): ConnectorAuthorizationVerdict! "Complete an in-progress Appointment: the optional orderId LINKS the billing order at the last legal moment (completed is immutable) — it must be an in-tenant non-doomed-class Order (CONFLICT/REF_STATE else); auto-minting an order line is a named growth. Requires the unrestricted capability + the record's CURRENT revision." completeAppointment(input: CompleteAppointmentInput!): Appointment! "Reschedule a requested/confirmed Appointment in ONE transaction: the predecessor flips rescheduled (slot RELEASED — the RESBOOK rows delete) and the SUCCESSOR births requested with every other field copied verbatim + the bilateral linkage ids stamped. The successor's own confirm re-runs the capacity gate (never auto-confirmed). The new window re-runs the lead/advance create gates; a resource re-pick re-gates in-tenant + ACTIVE + same-LF. Requires the unrestricted capability + the predecessor's CURRENT revision (OCC)." rescheduleAppointment(input: RescheduleAppointmentInput!): AppointmentReschedule! "File a claim on an ACTIVE Warranty: links a warranty_claim CsCase BOTH ways in ONE transaction (the warranty’s caseId + the case’s warrantyId); the maker/supplier routing is the snapshotted provider. Refuses CONFLICT/EXPIRED on an expired warranty, CONFLICT/REF_STATE on a non-warranty or closed/cancelled case, CONFLICT/REVISION_STALE on a stale expectedRevision; a claimed warranty declares no further edge (claim resolution is the deferred sub-flow)." fileClaimWarranty(input: ClaimWarrantyInput!): Warranty! "Rotate the signing key of an AgentChannel: the engine mints a FRESH ES256 keypair — the new public JWK joins the record's signingKeys as the current key, the outgoing key gains retiresAt = now + 7 days (the spec's grace — platforms keep verifying with it until then), keys already past their retiresAt are pruned, and the private halves rewrite the AGKEY credential row (never on the wire: nothing to paste). Allowed in every live state (draft · live · paused); a doomed channel refuses CONFLICT/IMMUTABLE. OCC by revision (CONFLICT/REVISION_STALE). Requires the unrestricted capability (the class)." rotateAgentChannelKey(id: ID!, revision: ID!, reason: String): AgentChannel! "THE AGENT CHECKOUT — create: open a UCP checkout session on the AgentChannel — a DRAFT Order on the ecom channel at the channel's selling location, validUntil = now + the channel's checkout TTL, the lines priced through the channel's PriceList plane, THE AGENT CHECKOUT BLOCK stamped — and answer the quote (lines · totals · the fulfillment offer · consent · the discount extension's codes + applied discounts · the status rule + messages). Lines whose variant is not LISTED are dropped with item_unavailable messages; when NONE remain the create refuses VALIDATION/INVALID (nothing is born). The agent_platform principal opens on its OWN channel (platformProfileUrl comes from its session — an explicit arg refuses); staff (write) may name a platformProfileUrl for a test drive or none." agentChannelCheckoutCreate(agentChannelId: ID!, input: AgentCheckoutInput!, platformProfileUrl: String, linkedConsumerId: ID): AgentCheckout! "THE AGENT CHECKOUT — update: FULL REPLACEMENT (the released law) — the lines re-captured at this instant, the buyer and the fulfillment choice replaced, the discount codes applied with replacement semantics when given — then the fresh quote. A terminal checkout (completed · canceled) refuses CONFLICT/REF_STATE." agentChannelCheckoutUpdate(agentChannelId: ID!, orderId: ID!, input: AgentCheckoutInput!, linkedConsumerId: ID): AgentCheckout! "THE AGENT CHECKOUT — cancel: the draft's own cancel transition (terminal); a completed/canceled checkout refuses CONFLICT/REF_STATE. Answers the view with status canceled." agentChannelCheckoutCancel(agentChannelId: ID!, orderId: ID!, reason: String, linkedConsumerId: ID): AgentCheckout! "THE AGENT CHECKOUT — complete: pay and place a ready_for_complete checkout with the ONE selected instrument — the mint of the PLACED sale from the draft (the fee in the money · the seats copied · the ecom reservation · real tax at the origin) → the card hold through the advertised handler (Google Pay via Stripe; a tok_/pm_ credential) → the draft's own draft → accepted flip → status completed with order { id, sysId } + the display-safe payment echo. A decline cancels the pending sale and answers the checkout ready_for_complete with a recoverable payment_failed message; insufficient stock answers incomplete + out_of_stock; a lapsed validity answers canceled; a completed/canceled checkout refuses CONFLICT/REF_STATE (the door speaks checkout_closed); a pending mint (the crash window) reads complete_in_progress and RESUMES here. An instrument naming a handler this business does not advertise refuses VALIDATION/INVALID." agentChannelCheckoutComplete(agentChannelId: ID!, orderId: ID!, input: AgentCheckoutCompleteInput!, linkedConsumerId: ID): AgentCheckout! "Issue the fiscal compliance artifact for an Order/Invoice: the regime roster gate → the STRICT parent gate (an Order rests at completed — model A signs at/after completion; an Invoice at issued/closed, voided refuses) → the certified FiscalizationPort (an UNCONFIGURED regime refuses FISCAL/REGIME_UNCONFIGURED — partners + per-country certs are build-time; a denial is FISCAL/CLEARANCE_FAILED, a timeout FISCAL/CLEARANCE_TIMEOUT [retry-safe: nothing issued]) → ONE transaction: the receipt + the gap-free series counter + the one-per-(document × regime) marker (a duplicate refuses CONFLICT/IDENTITY_TAKEN — gap-free journals never re-issue; the marker never releases). Requires the unrestricted capability." issueFiscalReceipt(input: IssueFiscalReceiptInput!): FiscalReceipt! "Mark an in_progress PrivacyRequest FULFILLED: the affected records link back via the refs (the de-identified Consumer, the export target, the rectified records — provable WHICH request drove WHICH scrubbing). affectedRefs ≥1 REQUIRED — an evidence-less fulfill refuses CONFLICT/INCOMPLETE (retryable: finish the actions, fulfill again); refs are advisory + tombstone-tolerant. OCC on the passed revision. Template class (privacy & compliance)." fulfillPrivacyRequest(id: ID!, revision: ID!, affectedRefs: [TaskConstructRefInput!]!, reason: String): PrivacyRequest! "Start ONE background search — a validated plan run AS YOU, in the background: the SearchPlanInput grammar VERBATIM, and the SAME PLAN GATE as searchPlanRun refuses BEFORE any read — an unknown family, a field outside its roster, a hop that is not a relationship of the current family — naming the legal words; a family you may not list refuses the whole plan. The job records the plan (`planJson`) and its words, runs ONE bounded step at a time (pages of 1000; at most 50000 records examined — the estimate refuses a plan that cannot fit, with the numbers; 300 s from the start → expired WITH the partials; at most 400 steps), and lands its matches as ONE result set for 7 days (read them with searchJobMatches). ONE running job per signed-in session — a second start refuses CONFLICT/SEARCH_JOB_ACTIVE naming the holder: wait for it to finish or cancel it. Where no machine is wired the same steps run inline and the job comes back finished. A JSON null on an optional input field reads as absent. Requires the unrestricted capability on a USER session (an API key or a collaborator refuses AUTHZ/FORBIDDEN — the job is yours: your user, your session)." startSearchJob(plan: SearchPlanInput!): SearchJob! "Cancel YOUR queued or running background search: the record flips to cancelled and the session's search slot frees at once; the machine notices at its next step boundary and keeps the partial matches it had — no execution is killed, nothing is lost. Only the job's OWNER (the same user AND the same session) may cancel — anyone else refuses AUTHZ/FORBIDDEN; a job outside your tenant, or none at all, is NOT_FOUND; a finished job refuses (terminal records are immutable). Requires the unrestricted capability on a USER session." cancelSearchJob(id: ID!): SearchJob! "Start ONE background export — a validated plan run AS YOU, in the background, whose LAST family's records are written to a file: the SearchPlanInput grammar VERBATIM, and the SAME PLAN GATE as searchPlanRun refuses BEFORE any read — an unknown family, a field outside its roster, a hop that is not a relationship of the current family — naming the legal words; a family you may not list refuses the whole plan (the file carries the records exactly as the list lane would answer them to you). `format` picks the file: csv (RFC 4180 — the header is the union of every record's leaves, nested objects as dotted columns, arrays as JSON cells) or jsonl (one JSON record per line). 📊 The optional `report` turns the export into a BACKGROUND REPORT: the same ReportSpecInput reportRun takes — its `plan` MUST equal `plan` (one plan, two spellings never — refused VALIDATION/INVALID otherwise); the record carries the spec (`reportJson`) and its words become the report's; the file then holds the report's rows — a projection's chosen columns (the header = the columns in order; the `.caption` of the reference families you may list rides beside the ids, the others are omitted silently) or an aggregate's groups (count · sums · smallest · largest · average per currency; more than 1000 groups FAILS the job with the words — no file of half-truths). The job records the plan (`planJson`) and its words, runs ONE bounded step at a time (pages of 1000; at most 50000 records examined — the estimate refuses a plan that cannot fit, with the numbers; 300 s from the start → expired WITH the rows written so far; at most 400 steps; a file past 256 MiB halts partial), writing EVERY record of the last family (the plan's limit does not bound an export), and composes THE FILE at the finish — downloadable for 7 days through exportJobDownload; an in-app notice tells you when it lands. ONE running export per signed-in session — a second start refuses CONFLICT/EXPORT_JOB_ACTIVE naming the holder: wait for it to finish or cancel it. Where no machine is wired the same steps run inline and the job comes back finished. 📊 THE PLAN NAMED ONE WAY — reportId (a saved Report) XOR plan (+ optional report): a saved definition lifts its plan AND its spec — the export becomes that report, run as YOU, the spec re-validated now; only an active definition runs (an inactive or doomed one refuses CONFLICT/REF_STATE naming its state); reportId beside plan or report, or neither of them, refuses VALIDATION/INVALID. A JSON null on an optional input field reads as absent. Requires the unrestricted capability on a USER session (an API key or a collaborator refuses AUTHZ/FORBIDDEN — the job is yours: your user, your session)." startExportJob(plan: SearchPlanInput, format: ExportFormat!, report: ReportSpecInput, reportId: ID): ExportJob! "Cancel YOUR queued or running background export: the record flips to cancelled and the session's export slot frees at once; NO file is composed and no notice is sent — the parts already written age out on their own; the machine notices at its next step boundary and stops. Only the job's OWNER (the same user AND the same session) may cancel — anyone else refuses AUTHZ/FORBIDDEN; a job outside your tenant, or none at all, is NOT_FOUND; a finished job refuses (terminal records are immutable). Requires the unrestricted capability on a USER session." cancelExportJob(id: ID!): ExportJob! "Start ONE background wizard draft: hand the platform your text and/or your documents plus EVERY page's WANT at once, and the assistant drafts the WHOLE walk in the background at its highest effort — every value with its source and confidence, at most 5 questions, one advice paragraph; the record flips ready and the fill_draft_finished notice tells you. THE ORDER OF THE GATES: your group's wallet must exist (CONFLICT/REF_STATE — the call is charged like every assist) · the assistant offline or the machine unwired refuses INTEGRATION/UNAVAILABLE loudly (never a silent inline draft — fill the wizard by hand) · at most 12 starts an hour and 4 open drafts (VALIDATION/INVALID) · ONE draft is made at a time per person (CONFLICT/FILL_DRAFT_ACTIVE naming the holder — wait for it, or abandon it) · a document that is not yours or not on this wizard word is NOT_FOUND. DRAFTS ONLY — nothing is created or applied; you review every value (the wizard pages seed from the sheet). A JSON null on an optional input field reads as absent. Requires the unrestricted capability on a USER session. Template class (universal staff work)." startFillDraft(input: StartFillDraftInput!): FillDraft! "Close ONE of YOUR wizard drafts: drafting or ready → abandoned; a draft still being made is cancelled with the assistant as far as it can be, and your drafting slot frees at once. Another state refuses CONFLICT/REF_STATE naming it; another person's draft, or none at all, is NOT_FOUND. Requires the unrestricted capability on a USER session. Template class." abandonFillDraft(id: ID!): FillDraft! "Take ONE of YOUR READY wizard drafts into a record: the office fires it AFTER the wizard's create lands — the moment the sheet was consumed; ready → taken SET ONCE with takenAt stamped. Another state refuses CONFLICT/REF_STATE naming it (a second take is that refusal; an expired draft refuses too); another person's draft, or none at all, is NOT_FOUND. A taken draft stays in your list as history until its lifetime ends and takes no more messages. Nothing is created here — the record was born by its own wizard. 🤖: takenRef (optional, 1..64) names the record the draft became — its sysId or its id — and rides the same flip (a malformed reference refuses VALIDATION/INVALID before anything is read). Requires the unrestricted capability on a USER session. Template class." takeFillDraft(id: ID!, takenRef: String): FillDraft! "Tell the assistant what to change on ONE of YOUR READY wizard drafts: your message (say) and optionally more of your documents go in; your turn is appended and the draft flips back to drafting while the assistant answers in the background — briefly, in plain words — and hands back the WHOLE revised sheet (every value you did not ask about kept; a value you rejected removed); the draft flips ready again and the fill_draft_finished notice tells you. When the conversation outgrows 12 un-summarized turns the older turns FOLD into the stored summary first. The assistant cannot look anything up — it asks you for facts it lacks. THE ORDER OF THE GATES: the draft must be yours and ready (CONFLICT/REF_STATE naming another state; an expired draft refuses too) with its current revision (CONFLICT/REVISION_STALE) · at most 24 turns per draft and 30 messages an hour (VALIDATION/INVALID) · the assistant offline or the machine unwired refuses INTEGRATION/UNAVAILABLE loudly · ONE draft is worked on at a time per person (CONFLICT/FILL_DRAFT_ACTIVE naming the holder) · a document that is not yours or not on this wizard word is NOT_FOUND. A failed answer is TOLD on the transcript (outcome failed) and the sheet stays as it was. DRAFTS ONLY — nothing is created or applied. A JSON null on an optional input field reads as absent. Requires the unrestricted capability on a USER session. Template class (universal staff work)." talkFillDraft(input: TalkFillDraftInput!): TalkFillDraftResult! "Start YOUR OWN sitting of a course's test: the platform draws 10 ACTIVE questions of the course (every active question when fewer; below 3 refuses CONFLICT/TRAINING_TOO_FEW_QUESTIONS) and stores EXACTLY that draw on the record; passMark = the strictest active requirement binding your roles for the course, else 80. ONE open sitting per course (CONFLICT/TRAINING_ATTEMPT_OPEN names the holder); at most 5 sittings per course per UTC day (CONFLICT/TRAINING_CAP). courseKey must be a live play key (VALIDATION otherwise). Requires the unrestricted capability on a USER session." startTrainingAttempt(courseKey: String!): TrainingAttempt! "Hand in YOUR OWN open sitting — one option index (0-based) per drawn question, in the draw order (a wrong count, or an index past its question's options, refuses VALIDATION): graded SERVER-SIDE against the STORED draw — score 0..100, passed = score at or above passMark. A PASS mints your TrainingCertificate, tells you (the training_certificate_issued notice) and supersedes your earlier certificate for the course, all in the SAME transaction. open → submitted (terminal): a submitted or doomed sitting refuses CONFLICT/FSM_TRANSITION_INVALID; another person's sitting refuses AUTHZ/FORBIDDEN. Requires the unrestricted capability on a USER session + the CURRENT revision." submitTrainingAttempt(id: ID!, revision: ID!, answers: [Int!]!): TrainingAttempt! "Retire an abandoned OPEN sitting (open → doomed, terminal — never graded) so the person can start again; the course's open slot frees in the same write. Requires the unrestricted capability + the training-manage right + the CURRENT revision." doomTrainingAttempt(id: ID!, revision: ID!, reason: String): TrainingAttempt! "Withdraw a certificate (valid → revoked, terminal) WITH a reason — required (1..256 characters), it rides the revision's cause; the requirement reads unmet until the person passes again. Requires the unrestricted capability + the training-manage right + the CURRENT revision." revokeTrainingCertificate(id: ID!, revision: ID!, reason: String!): TrainingCertificate! "Note that YOU read ONE step of ONE play: your own progress record's step ledger — sorted, unique, IDEMPOTENT (a step already read is a no-op success, nothing written). playKey must be a live play key and stepN one of its steps (VALIDATION otherwise). Requires the unrestricted capability on a USER session." recordLessonRead(playKey: String!, stepN: Int!): MyTrainingPlayProgress! "Start YOUR OWN practice of a course's test (🎓: the SAME draw a sitting makes (10 ACTIVE questions, every one when fewer; below 3 refuses CONFLICT/TRAINING_TOO_FEW_QUESTIONS) written into your own progress record — a NEW start REPLACES an open practice (never a conflict); at most 20 starts per course per UTC day (CONFLICT/TRAINING_CAP · cap practice_per_day). passMark = the strictest active requirement binding your roles for the course, else 80. The answer carries NO keys. A practice never touches your sittings, never mints a certificate, never notifies. Requires the unrestricted capability on a USER session." startTrainingPractice(courseKey: String!): TrainingPracticeSitting! "Hand in YOUR OWN open practice — one option index (0-based) per drawn question, in the draw order (a wrong count, or an index past its question's options, refuses VALIDATION; no open practice refuses CONFLICT/TRAINING_PRACTICE_NOT_OPEN): graded SERVER-SIDE against the CURRENT questions (one retired for good since the start counts as missed) — score 0..100, passed = score at or above your pass mark; the right answers, the explanations and your picks come back. The last result replaces the previous one in your own progress record; nothing is certified. Requires the unrestricted capability on a USER session." submitTrainingPractice(courseKey: String!, answers: [Int!]!): TrainingPracticeResult! "Create a PhysicalFacilityLocation in the caller's org group; requires the unrestricted capability." createPhysicalFacilityLocation(input: NewPhysicalFacilityLocationInput!): PhysicalFacilityLocation! "Doom (terminal) a PhysicalFacilityLocation by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards: a PFL still referenced by a live PhysicalFacility is refused (CONFLICT/REFERENCED — detail carries the blocking refs); a non-active PFL is refused (CONFLICT/FSM_TRANSITION_INVALID). A cross-tenant id is forbidden + trips the rootId tripwire. The optional reason rides the transition events." doomPhysicalFacilityLocation(id: ID!, revision: ID!, reason: String): PhysicalFacilityLocation! "Edit a PhysicalFacilityLocation's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied taxJurisdictionId re-gates like create (exists + ACTIVE on the shared canonical tree); explicit null CLEARS the classification — the location returns to unclassified (zero tax, disclosed)." updatePhysicalFacilityLocation(id: ID!, revision: ID!, input: EditPhysicalFacilityLocationInput!): PhysicalFacilityLocation! "Create a PhysicalFacility in the caller's org group; requires the unrestricted capability." createPhysicalFacility(input: NewPhysicalFacilityInput!): PhysicalFacility! "Deactivate a PhysicalFacility by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivatePhysicalFacility(id: ID!, revision: ID!, reason: String): PhysicalFacility! "Reactivate a PhysicalFacility by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivatePhysicalFacility(id: ID!, revision: ID!, reason: String): PhysicalFacility! "Doom (terminal) a PhysicalFacility by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed PF is immutable + never deleted. The optional reason rides the transition events." doomPhysicalFacility(id: ID!, revision: ID!, reason: String): PhysicalFacility! "Edit a PhysicalFacility's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied physicalFacilityLocationId re-points the PF: the new PFL is tenant-scoped (cross-tenant → forbidden + tripwire) and must be active (CONFLICT/REF_STATE); the old PFL frees implicitly." updatePhysicalFacility(id: ID!, revision: ID!, input: EditPhysicalFacilityInput!): PhysicalFacility! "Create a LogicalFacility in the caller's org group; requires the unrestricted capability." createLogicalFacility(input: NewLogicalFacilityInput!): LogicalFacility! "Deactivate a LogicalFacility by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateLogicalFacility(id: ID!, revision: ID!, reason: String): LogicalFacility! "Reactivate a LogicalFacility by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateLogicalFacility(id: ID!, revision: ID!, reason: String): LogicalFacility! "Doom (terminal) a LogicalFacility by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed LF is immutable + never deleted. The optional reason rides the transition events." doomLogicalFacility(id: ID!, revision: ID!, reason: String): LogicalFacility! "Edit a LogicalFacility's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The classification is NOT editable (locked); nor is the parent-PF ref. A supplied geographicDivisionId re-gates like create (in-tenant + ACTIVE + geographic + selection-held); explicit null LEAVES the division (never gated)." updateLogicalFacility(id: ID!, revision: ID!, input: EditLogicalFacilityInput!): LogicalFacility! "Create a Zone in the caller's org group; requires the unrestricted capability." createZone(input: NewZoneInput!): Zone! "Deactivate a Zone by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateZone(id: ID!, revision: ID!, reason: String): Zone! "Reactivate a Zone by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateZone(id: ID!, revision: ID!, reason: String): Zone! "Doom (terminal) a Zone by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Zone is immutable + never deleted. The optional reason rides the transition events." doomZone(id: ID!, revision: ID!, reason: String): Zone! "Edit a Zone's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The parent-LF ref is NOT editable here." updateZone(id: ID!, revision: ID!, input: EditZoneInput!): Zone! "Create a Bin in the caller's org group; requires the unrestricted capability." createBin(input: NewBinInput!): Bin! "Deactivate a Bin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateBin(id: ID!, revision: ID!, reason: String): Bin! "Reactivate a Bin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateBin(id: ID!, revision: ID!, reason: String): Bin! "Doom (terminal) a Bin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Bin is immutable + never deleted. The optional reason rides the transition events." doomBin(id: ID!, revision: ID!, reason: String): Bin! "Edit a Bin's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The parent-Zone ref is NOT editable here." updateBin(id: ID!, revision: ID!, input: EditBinInput!): Bin! "Create a Role in the caller's org group; requires the unrestricted capability." createRole(input: NewRoleInput!): Role! "Deactivate a Role by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards: a Role still held by a non-doomed User (orgRoles) is refused (CONFLICT/REFERENCED — detail carries the blocking refs, STRICT). The optional reason rides the transition events." deactivateRole(id: ID!, revision: ID!, reason: String): Role! "Reactivate a Role by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateRole(id: ID!, revision: ID!, reason: String): Role! "Doom (terminal) a Role by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Role is immutable + never deleted. The optional reason rides the transition events." doomRole(id: ID!, revision: ID!, reason: String): Role! "Edit a Role's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateRole(id: ID!, revision: ID!, input: EditRoleInput!): Role! "Create a User in the caller's org group; requires the unrestricted capability." createUser(input: NewUserInput!): User! "Deactivate a User by id; requires the unrestricted capability + the record's CURRENT revision. THE RULED SESSION SEMANTICS: the user's live Sessions never block this transition and are NOT revoked — they go INERT at their next resolve (the live-status extension re-reads the User every call) and come back if the user is reactivated within their deadlines. The referential_integrity guard is consulted and returns unblocked ON THIS EDGE by ruling: live minted ApiKeys never block the reversible pause — key liveness reads only the minter Account's status + live ownerships, never the User's status, so the keys keep working and the doom edge is where disposition is forced. CS-Case assignedTo joins at its routing slice. The optional reason rides the transition events." deactivateUser(id: ID!, revision: ID!, reason: String): User! "Reactivate a User by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateUser(id: ID!, revision: ID!, reason: String): User! "Doom a User by id; requires the unrestricted capability + the record's CURRENT revision (OCC). Sessions never block and never cascade (the RULED semantics): the doomed user's sessions go INERT at their next resolve and ride to their own natural terminal. An ACTIVE ApiKey minted by this user BLOCKS the doom → CONFLICT/REFERENCED naming the keys: ApiKey has no parent-doom cascade, so key disposition is explicit — doom the keys (or let them expire) first; terminal keys never block. The (account × group) userBinding marker stays with the doomed record as history and is taken over by a future re-add — dooming never permanently strands the pair. The optional reason rides the transition events." doomUser(id: ID!, revision: ID!, reason: String): User! "Edit a User's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. updateUser IS the / user-role ASSIGNMENT op: supplying orgRoles replaces the full set after STRICT ref validation (each org + role in-tenant AND active)." updateUser(id: ID!, revision: ID!, input: EditUserInput!): User! "Create a Brand in the caller's org group; requires the unrestricted capability." createBrand(input: NewBrandInput!): Brand! "Deactivate a Brand by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateBrand(id: ID!, revision: ID!, reason: String): Brand! "Reactivate a Brand by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateBrand(id: ID!, revision: ID!, reason: String): Brand! "Doom (terminal) a Brand by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Brand is immutable + never deleted. The optional reason rides the transition events." doomBrand(id: ID!, revision: ID!, reason: String): Brand! "Edit a Brand's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateBrand(id: ID!, revision: ID!, input: EditBrandInput!): Brand! "Create a Season in the caller's org group; requires the unrestricted capability." createSeason(input: NewSeasonInput!): Season! "Deactivate a Season by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateSeason(id: ID!, revision: ID!, reason: String): Season! "Reactivate a Season by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateSeason(id: ID!, revision: ID!, reason: String): Season! "Doom (terminal) a Season by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Season is immutable + never deleted. The optional reason rides the transition events." doomSeason(id: ID!, revision: ID!, reason: String): Season! "Edit a Season's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateSeason(id: ID!, revision: ID!, input: EditSeasonInput!): Season! "Create a Tag in the caller's org group; requires the unrestricted capability." createTag(input: NewTagInput!): Tag! "Doom (terminal) a Tag by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Tag is immutable + never deleted. The optional reason rides the transition events." doomTag(id: ID!, revision: ID!, reason: String): Tag! "Edit a Tag's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTag(id: ID!, revision: ID!, input: EditTagInput!): Tag! "Create a Characteristic in the caller's org group; requires the unrestricted capability. Canned templates are copied via copyCannedCharacteristic instead." createCharacteristic(input: NewCharacteristicInput!): Characteristic! "Doom (terminal) a Characteristic by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Characteristic is immutable + never deleted. The optional reason rides the transition events." doomCharacteristic(id: ID!, revision: ID!, reason: String): Characteristic! "Edit a Characteristic's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCharacteristic(id: ID!, revision: ID!, input: EditCharacteristicInput!): Characteristic! "Create a CustomUom in the caller's org group; requires the unrestricted capability." createCustomUom(input: NewCustomUomInput!): CustomUom! "Deactivate a CustomUom by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateCustomUom(id: ID!, revision: ID!, reason: String): CustomUom! "Reactivate a CustomUom by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCustomUom(id: ID!, revision: ID!, reason: String): CustomUom! "Doom (terminal) a CustomUom by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Custom UoM is immutable + never deleted. The optional reason rides the transition events." doomCustomUom(id: ID!, revision: ID!, reason: String): CustomUom! "Edit a CustomUom's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCustomUom(id: ID!, revision: ID!, input: EditCustomUomInput!): CustomUom! "Create a Manufacturer in the caller's org group; requires the unrestricted capability." createManufacturer(input: NewManufacturerInput!): Manufacturer! "Deactivate a Manufacturer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateManufacturer(id: ID!, revision: ID!, reason: String): Manufacturer! "Reactivate a Manufacturer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateManufacturer(id: ID!, revision: ID!, reason: String): Manufacturer! "Doom (terminal) a Manufacturer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Manufacturer is immutable + never deleted. The optional reason rides the transition events." doomManufacturer(id: ID!, revision: ID!, reason: String): Manufacturer! "Edit a Manufacturer's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateManufacturer(id: ID!, revision: ID!, input: EditManufacturerInput!): Manufacturer! "Create a Vendor in the caller's org group; requires the unrestricted capability." createVendor(input: NewVendorInput!): Vendor! "Deactivate a Vendor by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateVendor(id: ID!, revision: ID!, reason: String): Vendor! "Reactivate a Vendor by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateVendor(id: ID!, revision: ID!, reason: String): Vendor! "Doom (terminal) a Vendor by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Vendor is immutable + never deleted. The optional reason rides the transition events." doomVendor(id: ID!, revision: ID!, reason: String): Vendor! "Edit a Vendor's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateVendor(id: ID!, revision: ID!, input: EditVendorInput!): Vendor! "Create a Category in the caller's org group; requires the unrestricted capability." createCategory(input: NewCategoryInput!): Category! "Deactivate a Category by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateCategory(id: ID!, revision: ID!, reason: String): Category! "Reactivate a Category by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCategory(id: ID!, revision: ID!, reason: String): Category! "Doom (terminal) a Category by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Category is immutable + never deleted. The optional reason rides the transition events." doomCategory(id: ID!, revision: ID!, reason: String): Category! "Edit a Category's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The merchandise-Division pointer follows the same gates (merchandise-type target) and clears with explicit null; both pointers stay mutually exclusive on the merged record." updateCategory(id: ID!, revision: ID!, input: EditCategoryInput!): Category! "Create a Division in the caller's org group; requires the unrestricted capability." createDivision(input: NewDivisionInput!): Division! "Deactivate a Division by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateDivision(id: ID!, revision: ID!, reason: String): Division! "Reactivate a Division by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateDivision(id: ID!, revision: ID!, reason: String): Division! "Doom (terminal) a Division by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Division is immutable + never deleted. The optional reason rides the transition events." doomDivision(id: ID!, revision: ID!, reason: String): Division! "Edit a Division's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateDivision(id: ID!, revision: ID!, input: EditDivisionInput!): Division! "Create an OptionGroup in the caller's org group; requires the unrestricted capability." createOptionGroup(input: NewOptionGroupInput!): OptionGroup! "Deactivate a OptionGroup by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOptionGroup(id: ID!, revision: ID!, reason: String): OptionGroup! "Reactivate a OptionGroup by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOptionGroup(id: ID!, revision: ID!, reason: String): OptionGroup! "Doom (terminal) a OptionGroup by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OptionGroup is immutable + never deleted. The optional reason rides the transition events." doomOptionGroup(id: ID!, revision: ID!, reason: String): OptionGroup! "Edit a OptionGroup's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOptionGroup(id: ID!, revision: ID!, input: EditOptionGroupInput!): OptionGroup! "Create an OptionValue under an OptionGroup in the caller's org group; requires the unrestricted capability." createOptionValue(input: NewOptionValueInput!): OptionValue! "Deactivate a OptionValue by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOptionValue(id: ID!, revision: ID!, reason: String): OptionValue! "Reactivate a OptionValue by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOptionValue(id: ID!, revision: ID!, reason: String): OptionValue! "Doom (terminal) a OptionValue by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OptionValue is immutable + never deleted. The optional reason rides the transition events." doomOptionValue(id: ID!, revision: ID!, reason: String): OptionValue! "Edit a OptionValue's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The parent-group ref is NOT editable here." updateOptionValue(id: ID!, revision: ID!, input: EditOptionValueInput!): OptionValue! "Create a Decoration in the caller's org group; requires the unrestricted capability." createDecoration(input: NewDecorationInput!): Decoration! "Deactivate a Decoration by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateDecoration(id: ID!, revision: ID!, reason: String): Decoration! "Reactivate a Decoration by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateDecoration(id: ID!, revision: ID!, reason: String): Decoration! "Doom (terminal) a Decoration by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Decoration is immutable + never deleted. The optional reason rides the transition events." doomDecoration(id: ID!, revision: ID!, reason: String): Decoration! "Edit a Decoration's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateDecoration(id: ID!, revision: ID!, input: EditDecorationInput!): Decoration! "Create an OrgManufacturer selection — the per-org ENABLEMENT of a group Manufacturer; requires the unrestricted capability." createOrgManufacturer(input: NewOrgManufacturerInput!): OrgManufacturer! "Deactivate a OrgManufacturer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgManufacturer(id: ID!, revision: ID!, reason: String): OrgManufacturer! "Reactivate a OrgManufacturer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgManufacturer(id: ID!, revision: ID!, reason: String): OrgManufacturer! "Doom (terminal) a OrgManufacturer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgManufacturer is immutable + never deleted. The optional reason rides the transition events." doomOrgManufacturer(id: ID!, revision: ID!, reason: String): OrgManufacturer! "Edit a OrgManufacturer's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgManufacturer(id: ID!, revision: ID!, input: EditOrgManufacturerInput!): OrgManufacturer! "Create an OrgBrand selection — the per-org ENABLEMENT of a group Brand; requires the unrestricted capability." createOrgBrand(input: NewOrgBrandInput!): OrgBrand! "Deactivate a OrgBrand by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgBrand(id: ID!, revision: ID!, reason: String): OrgBrand! "Reactivate a OrgBrand by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgBrand(id: ID!, revision: ID!, reason: String): OrgBrand! "Doom (terminal) a OrgBrand by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgBrand is immutable + never deleted. The optional reason rides the transition events." doomOrgBrand(id: ID!, revision: ID!, reason: String): OrgBrand! "Edit a OrgBrand's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgBrand(id: ID!, revision: ID!, input: EditOrgBrandInput!): OrgBrand! "Create an OrgSeason selection — the per-org ENABLEMENT of a group Season; requires the unrestricted capability." createOrgSeason(input: NewOrgSeasonInput!): OrgSeason! "Deactivate a OrgSeason by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgSeason(id: ID!, revision: ID!, reason: String): OrgSeason! "Reactivate a OrgSeason by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgSeason(id: ID!, revision: ID!, reason: String): OrgSeason! "Doom (terminal) a OrgSeason by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgSeason is immutable + never deleted. The optional reason rides the transition events." doomOrgSeason(id: ID!, revision: ID!, reason: String): OrgSeason! "Edit a OrgSeason's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgSeason(id: ID!, revision: ID!, input: EditOrgSeasonInput!): OrgSeason! "Create an OrgDivision selection — the per-org ENABLEMENT of a group Division; requires the unrestricted capability." createOrgDivision(input: NewOrgDivisionInput!): OrgDivision! "Deactivate a OrgDivision by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgDivision(id: ID!, revision: ID!, reason: String): OrgDivision! "Reactivate a OrgDivision by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgDivision(id: ID!, revision: ID!, reason: String): OrgDivision! "Doom (terminal) a OrgDivision by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgDivision is immutable + never deleted. The optional reason rides the transition events." doomOrgDivision(id: ID!, revision: ID!, reason: String): OrgDivision! "Edit a OrgDivision's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgDivision(id: ID!, revision: ID!, input: EditOrgDivisionInput!): OrgDivision! "Create an OrgVendor selection — the per-org ENABLEMENT of a group Vendor; requires the unrestricted capability." createOrgVendor(input: NewOrgVendorInput!): OrgVendor! "Deactivate a OrgVendor by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgVendor(id: ID!, revision: ID!, reason: String): OrgVendor! "Reactivate a OrgVendor by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgVendor(id: ID!, revision: ID!, reason: String): OrgVendor! "Doom (terminal) a OrgVendor by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgVendor is immutable + never deleted. The optional reason rides the transition events." doomOrgVendor(id: ID!, revision: ID!, reason: String): OrgVendor! "Edit a OrgVendor's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgVendor(id: ID!, revision: ID!, input: EditOrgVendorInput!): OrgVendor! "Create a Style in the caller's org group; requires the unrestricted capability." createStyle(input: NewStyleInput!): Style! "Deactivate a Style by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateStyle(id: ID!, revision: ID!, reason: String): Style! "Reactivate a Style by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateStyle(id: ID!, revision: ID!, reason: String): Style! "Doom (terminal) a Style by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Style is immutable + never deleted. The optional reason rides the transition events." doomStyle(id: ID!, revision: ID!, reason: String): Style! "Edit a Style's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied scheme replaces wholesale but is REFUSED once any Product exists; brandId and sizeRunId clear with explicit null; the other lists replace wholesale (empty releases) — every supplied entry re-gated like create." updateStyle(id: ID!, revision: ID!, input: EditStyleInput!): Style! "Create a Product under a Style in the caller's org group; requires the unrestricted capability." createProduct(input: NewProductInput!): Product! "Deactivate a Product by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateProduct(id: ID!, revision: ID!, reason: String): Product! "Reactivate a Product by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateProduct(id: ID!, revision: ID!, reason: String): Product! "Doom (terminal) a Product by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Product is immutable + never deleted. The optional reason rides the transition events." doomProduct(id: ID!, revision: ID!, reason: String): Product! "Edit a Product's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied segment is no-orphan-gated (every non-doomed variant must remain inside it); a supplied rrp keeps at least 1 entry and stays floor-gated under live selections." updateProduct(id: ID!, revision: ID!, input: EditProductInput!): Product! "Create a Variant under a Product in the caller's org group; requires the unrestricted capability." createVariant(input: NewVariantInput!): Variant! "Deactivate a Variant by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateVariant(id: ID!, revision: ID!, reason: String): Variant! "Reactivate a Variant by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateVariant(id: ID!, revision: ID!, reason: String): Variant! "Doom (terminal) a Variant by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Variant is immutable + never deleted. The optional reason rides the transition events." doomVariant(id: ID!, revision: ID!, reason: String): Variant! "Edit a Variant's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateVariant(id: ID!, revision: ID!, input: EditVariantInput!): Variant! "Create an OrgStyle selection — the per-org ENABLEMENT of a group Style; requires the unrestricted capability." createOrgStyle(input: NewOrgStyleInput!): OrgStyle! "Deactivate a OrgStyle by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgStyle(id: ID!, revision: ID!, reason: String): OrgStyle! "Reactivate a OrgStyle by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgStyle(id: ID!, revision: ID!, reason: String): OrgStyle! "Doom (terminal) a OrgStyle by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgStyle is immutable + never deleted. The optional reason rides the transition events." doomOrgStyle(id: ID!, revision: ID!, reason: String): OrgStyle! "Edit a OrgStyle's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgStyle(id: ID!, revision: ID!, input: EditOrgStyleInput!): OrgStyle! "Create a ProductRelation — a typed, directed, ranked suggestion edge; requires the unrestricted capability." createProductRelation(input: NewProductRelationInput!): ProductRelation! "Deactivate a ProductRelation by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateProductRelation(id: ID!, revision: ID!, reason: String): ProductRelation! "Reactivate a ProductRelation by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateProductRelation(id: ID!, revision: ID!, reason: String): ProductRelation! "Doom (terminal) a ProductRelation by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed ProductRelation is immutable + never deleted. The optional reason rides the transition events." doomProductRelation(id: ID!, revision: ID!, reason: String): ProductRelation! "Edit a ProductRelation's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateProductRelation(id: ID!, revision: ID!, input: EditProductRelationInput!): ProductRelation! "Create a Collection in the caller's org group; requires the unrestricted capability." createCollection(input: NewCollectionInput!): Collection! "Deactivate a Collection by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateCollection(id: ID!, revision: ID!, reason: String): Collection! "Reactivate a Collection by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCollection(id: ID!, revision: ID!, reason: String): Collection! "Doom (terminal) a Collection by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Collection is immutable + never deleted. The optional reason rides the transition events." doomCollection(id: ID!, revision: ID!, reason: String): Collection! "Edit a Collection's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCollection(id: ID!, revision: ID!, input: EditCollectionInput!): Collection! "Create a CollectionMember — one curated membership/pin edge; requires the unrestricted capability." createCollectionMember(input: NewCollectionMemberInput!): CollectionMember! "Doom (terminal) a CollectionMember by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed CollectionMember is immutable + never deleted. The optional reason rides the transition events." doomCollectionMember(id: ID!, revision: ID!, reason: String): CollectionMember! "Edit a CollectionMember's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCollectionMember(id: ID!, revision: ID!, input: EditCollectionMemberInput!): CollectionMember! "Create a VariantComponent — one BOM edge; requires the unrestricted capability." createVariantComponent(input: NewVariantComponentInput!): VariantComponent! "Doom (terminal) a VariantComponent by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed VariantComponent is immutable + never deleted. The optional reason rides the transition events." doomVariantComponent(id: ID!, revision: ID!, reason: String): VariantComponent! "Edit a VariantComponent's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateVariantComponent(id: ID!, revision: ID!, input: EditVariantComponentInput!): VariantComponent! "Create an InventoryItem — the explicit stock junction; requires the unrestricted capability." createInventoryItem(input: NewInventoryItemInput!): InventoryItem! "Deactivate a InventoryItem by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateInventoryItem(id: ID!, revision: ID!, reason: String): InventoryItem! "Reactivate a InventoryItem by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateInventoryItem(id: ID!, revision: ID!, reason: String): InventoryItem! "Doom (terminal) a InventoryItem by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed InventoryItem is immutable + never deleted. The optional reason rides the transition events." doomInventoryItem(id: ID!, revision: ID!, reason: String): InventoryItem! "Edit a InventoryItem's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateInventoryItem(id: ID!, revision: ID!, input: EditInventoryItemInput!): InventoryItem! "Create a SalePrice — the splice insert; requires the unrestricted capability." createSalePrice(input: NewSalePriceInput!): SalePrice! "Cancel a SCHEDULED SalePrice window: allowed ONLY while the record is not yet effective (now < startAt). An effective or lapsed window is immutable price history — CONFLICT/IMMUTABLE naming startAt vs now; supersede it with a new window instead. Requires the current revision (OCC) + the unrestricted capability; the record is kept, excluded from the schedule (no-delete)." doomSalePrice(id: ID!, revision: ID!, reason: String): SalePrice! "Edit a SalePrice's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateSalePrice(id: ID!, revision: ID!, input: EditSalePriceInput!): SalePrice! "Edit a Transfer's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTransfer(id: ID!, revision: ID!, input: EditTransferInput!): Transfer! "Edit a TransferRequest's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTransferRequest(id: ID!, revision: ID!, input: EditTransferRequestInput!): TransferRequest! "Edit a Count's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCount(id: ID!, revision: ID!, input: EditCountInput!): Count! "Create a Contact in the caller's org group; requires the unrestricted capability." createContact(input: NewContactInput!): Contact! "Deactivate a Contact by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateContact(id: ID!, revision: ID!, reason: String): Contact! "Reactivate a Contact by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateContact(id: ID!, revision: ID!, reason: String): Contact! "Doom (terminal) a Contact by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Contact is immutable + never deleted. The optional reason rides the transition events." doomContact(id: ID!, revision: ID!, reason: String): Contact! "Edit a Contact's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateContact(id: ID!, revision: ID!, input: EditContactInput!): Contact! "Create a ContactAssignment — one role-tagged contact attachment; requires the unrestricted capability." createContactAssignment(input: NewContactAssignmentInput!): ContactAssignment! "Doom (terminal) a ContactAssignment by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed ContactAssignment is immutable + never deleted. The optional reason rides the transition events." doomContactAssignment(id: ID!, revision: ID!, reason: String): ContactAssignment! "Edit a ContactAssignment's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateContactAssignment(id: ID!, revision: ID!, input: EditContactAssignmentInput!): ContactAssignment! "Create a WarrantyTerms policy template in the caller's org group; requires the unrestricted capability." createWarrantyTerms(input: NewWarrantyTermsInput!): WarrantyTerms! "Deactivate a WarrantyTerms by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateWarrantyTerms(id: ID!, revision: ID!, reason: String): WarrantyTerms! "Reactivate a WarrantyTerms by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateWarrantyTerms(id: ID!, revision: ID!, reason: String): WarrantyTerms! "Doom (terminal) a WarrantyTerms by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed WarrantyTerms is immutable + never deleted. The optional reason rides the transition events." doomWarrantyTerms(id: ID!, revision: ID!, reason: String): WarrantyTerms! "Edit a WarrantyTerms's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateWarrantyTerms(id: ID!, revision: ID!, input: EditWarrantyTermsInput!): WarrantyTerms! "Edit a Warranty's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateWarranty(id: ID!, revision: ID!, input: EditWarrantyInput!): Warranty! "Create an OrgVendorItem — one (orgVendor × variant) purchasing junction; requires the unrestricted capability." createOrgVendorItem(input: NewOrgVendorItemInput!): OrgVendorItem! "Deactivate a OrgVendorItem by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgVendorItem(id: ID!, revision: ID!, reason: String): OrgVendorItem! "Reactivate a OrgVendorItem by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgVendorItem(id: ID!, revision: ID!, reason: String): OrgVendorItem! "Doom (terminal) a OrgVendorItem by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgVendorItem is immutable + never deleted. The optional reason rides the transition events." doomOrgVendorItem(id: ID!, revision: ID!, reason: String): OrgVendorItem! "Edit a OrgVendorItem's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgVendorItem(id: ID!, revision: ID!, input: EditOrgVendorItemInput!): OrgVendorItem! "Edit a PurchaseOrder's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePurchaseOrder(id: ID!, revision: ID!, input: EditPurchaseOrderInput!): PurchaseOrder! "Edit a Receipt's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateReceipt(id: ID!, revision: ID!, input: EditReceiptInput!): Receipt! "Edit a Rtv's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateRtv(id: ID!, revision: ID!, input: EditRtvInput!): Rtv! "Edit a VendorInvoice's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateVendorInvoice(id: ID!, revision: ID!, input: EditVendorInvoiceInput!): VendorInvoice! "Create a PurchasePack — one packaging definition on a variant; requires the unrestricted capability." createPurchasePack(input: NewPurchasePackInput!): PurchasePack! "Deactivate a PurchasePack by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivatePurchasePack(id: ID!, revision: ID!, reason: String): PurchasePack! "Reactivate a PurchasePack by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivatePurchasePack(id: ID!, revision: ID!, reason: String): PurchasePack! "Doom (terminal) a PurchasePack by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed PurchasePack is immutable + never deleted. The optional reason rides the transition events." doomPurchasePack(id: ID!, revision: ID!, reason: String): PurchasePack! "Edit a PurchasePack's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePurchasePack(id: ID!, revision: ID!, input: EditPurchasePackInput!): PurchasePack! "Create a ReplenishmentConfig — one cell of the planning parameter matrix; requires the unrestricted capability." createReplenishmentConfig(input: NewReplenishmentConfigInput!): ReplenishmentConfig! "Deactivate a ReplenishmentConfig by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateReplenishmentConfig(id: ID!, revision: ID!, reason: String): ReplenishmentConfig! "Reactivate a ReplenishmentConfig by id. ⚠ RE-RUNS the write-time collision gate: an ACTIVE same-tuple sibling setting an intersecting parameter refuses CONFLICT/IDENTITY_TAKEN naming the holder + the intersection. Requires the current `revision` and accepts an optional `reason`." reactivateReplenishmentConfig(id: ID!, revision: ID!, reason: String): ReplenishmentConfig! "Doom (terminal) a ReplenishmentConfig by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed ReplenishmentConfig is immutable + never deleted. The optional reason rides the transition events." doomReplenishmentConfig(id: ID!, revision: ID!, reason: String): ReplenishmentConfig! "Edit a ReplenishmentConfig's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateReplenishmentConfig(id: ID!, revision: ID!, input: EditReplenishmentConfigInput!): ReplenishmentConfig! "Create a TransferLane — one directed source→destination sourcing declaration; requires the unrestricted capability." createTransferLane(input: NewTransferLaneInput!): TransferLane! "Deactivate a TransferLane by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateTransferLane(id: ID!, revision: ID!, reason: String): TransferLane! "Reactivate a TransferLane by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateTransferLane(id: ID!, revision: ID!, reason: String): TransferLane! "Doom (terminal) a TransferLane by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed TransferLane is immutable + never deleted. The optional reason rides the transition events." doomTransferLane(id: ID!, revision: ID!, reason: String): TransferLane! "Edit a TransferLane's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTransferLane(id: ID!, revision: ID!, input: EditTransferLaneInput!): TransferLane! "Create a TaxRegistration — the org's nexus declaration for one jurisdiction; requires the unrestricted capability." createTaxRegistration(input: NewTaxRegistrationInput!): TaxRegistration! "Deactivate a TaxRegistration by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateTaxRegistration(id: ID!, revision: ID!, reason: String): TaxRegistration! "Reactivate a TaxRegistration by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateTaxRegistration(id: ID!, revision: ID!, reason: String): TaxRegistration! "Doom (terminal) a TaxRegistration by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed TaxRegistration is immutable + never deleted. The optional reason rides the transition events." doomTaxRegistration(id: ID!, revision: ID!, reason: String): TaxRegistration! "Edit a TaxRegistration's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTaxRegistration(id: ID!, revision: ID!, input: EditTaxRegistrationInput!): TaxRegistration! "Capture an ExemptionCertificate; requires the unrestricted capability. The capture is immutable except caption/code/docRef — correct by revoke + re-capture (no revival from any terminal)." createExemptionCertificate(input: NewExemptionCertificateInput!): ExemptionCertificate! "Revoke an ExemptionCertificate by id; requires the unrestricted capability + the record's CURRENT revision. TERMINAL — no revival; re-capture a new cert. The optional reason rides the transition events." revokeExemptionCertificate(id: ID!, revision: ID!, reason: String): ExemptionCertificate! "Doom (terminal) a ExemptionCertificate by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed ExemptionCertificate is immutable + never deleted. The optional reason rides the transition events." doomExemptionCertificate(id: ID!, revision: ID!, reason: String): ExemptionCertificate! "Edit a ExemptionCertificate's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied orgCustomerId re-links the holder (re-gated in-tenant + non-doomed); explicit null UNLINKS it — unlinking frees a blocked holder doom." updateExemptionCertificate(id: ID!, revision: ID!, input: EditExemptionCertificateInput!): ExemptionCertificate! "Open an Order; requires the unrestricted capability." createOrder(input: NewOrderInput!): Order! "Park an open Order; requires the unrestricted capability + the record's CURRENT revision. Resumable via resumeOrder; the idle sweep abandons stale holds (dormant until the scheduler strand wires)." holdOrder(id: ID!, revision: ID!, reason: String): Order! "Resume a held Order to open; requires the unrestricted capability + the record's CURRENT revision." resumeOrder(id: ID!, revision: ID!, reason: String): Order! "Commit an open Order An empty cart refuses VALIDATION/INVALID; an attached cert failing at-USE validity refuses CONFLICT/EXPIRED. Requires the unrestricted capability + the record's CURRENT revision." placeOrder(id: ID!, revision: ID!, reason: String): Order! "Void an open Order; requires the unrestricted capability + the record's CURRENT revision. TERMINAL doomed-class — lists filter it; revival is a NEW Order." voidOrder(id: ID!, revision: ID!, reason: String): Order! "Cancel an Order per its profile: a placed sale cancels with per-line reservation release in THE transaction + the open-claims/tendered gates; a draft/quote cancels from draft or sent. Requires the unrestricted capability + the record's CURRENT revision. TERMINAL doomed-class — lists filter it." cancelOrder(id: ID!, revision: ID!, reason: String): Order! "Send a draft/quote to the customer. Content stays re-priceable until accepted. Requires the unrestricted capability + the record's CURRENT revision." sendOrder(id: ID!, revision: ID!, reason: String): Order! "Accept a sent draft/quote — THE CONVERSION: within the validity window (past validUntil refuses CONFLICT/EXPIRED — the policy:within_validity gate reads LIVE while the scheduled expire edges sleep), ONE transaction mints a NEW sale Order BORN-PLACED from the doc VERBATIM (captured prices — no re-price; the pipeline runs: REAL tax at the origin + the ecom reserve arm per stockful line + the composed budget) AND flips this doc accepted with convertedOrderId ↔ sourceDocumentId refs. An empty doc refuses VALIDATION/INVALID (the place empty-cart law). Requires the unrestricted capability + the record's CURRENT revision." acceptOrder(id: ID!, revision: ID!, reason: String): Order! "Edit a Order's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The birth-fixed fields (organizationId, channel, orderType, logicalFacilityId, currency) are not editable — void and open a new Order." updateOrder(id: ID!, revision: ID!, input: EditOrderInput!): Order! "Void an issued Invoice. The order's invoicedQty rollups UN-STAMP in THE transaction and the invoiceIds slot is REMOVED (the remainder becomes re-invoiceable and the slot re-opens; the surviving invoices' attribution re-flows); an invoice carrying non-voided CreditNotes/DebitNotes refuses CONFLICT/REFERENCED (void the notes first). Requires the unrestricted capability + the record's CURRENT revision. TERMINAL doomed-class — lists filter it." voidInvoice(id: ID!, revision: ID!, reason: String): Invoice! "Void an issued CreditNote. The invoice's notedBaseDeltaMinor rollups UN-STAMP in THE transaction (the credited headroom restores). Requires the unrestricted capability + the record's CURRENT revision. TERMINAL doomed-class — lists filter it." voidCreditNote(id: ID!, revision: ID!, reason: String): CreditNote! "Void an issued DebitNote. The invoice's notedBaseDeltaMinor rollups UN-STAMP in THE transaction. Requires the unrestricted capability + the record's CURRENT revision. TERMINAL doomed-class — lists filter it." voidDebitNote(id: ID!, revision: ID!, reason: String): DebitNote! "Request a Return; requires the unrestricted capability." createReturn(input: NewReturnInput!): Return! "Approve a requested Return; requires the unrestricted capability + the record's CURRENT revision." approveReturn(id: ID!, revision: ID!, reason: String): Return! "Reject a requested Return; requires the unrestricted capability + the record's CURRENT revision." rejectReturn(id: ID!, revision: ID!, reason: String): Return! "Cancel a Return before processing; requires the unrestricted capability + the record's CURRENT revision." cancelReturn(id: ID!, revision: ID!, reason: String): Return! "Finalize a refunded Return; requires the unrestricted capability + the record's CURRENT revision." closeReturn(id: ID!, revision: ID!, reason: String): Return! "Edit a Return's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The birth-fixed refs (orderId, invoiceId, logicalFacilityId) are not editable — cancel and request a new Return." updateReturn(id: ID!, revision: ID!, input: EditReturnInput!): Return! "Create a Register — a logical till position at an LF; requires the unrestricted capability." createRegister(input: NewRegisterInput!): Register! "Deactivate a Register by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateRegister(id: ID!, revision: ID!, reason: String): Register! "Reactivate a Register by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateRegister(id: ID!, revision: ID!, reason: String): Register! "Doom (terminal) a Register by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Register is immutable + never deleted. The optional reason rides the transition events." doomRegister(id: ID!, revision: ID!, reason: String): Register! "Edit a Register's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateRegister(id: ID!, revision: ID!, input: EditRegisterInput!): Register! "Suspend an open TillSession; requires the unrestricted capability + the record's CURRENT revision." suspendTillSession(id: ID!, revision: ID!, reason: String): TillSession! "Resume a suspended TillSession; requires the unrestricted capability + the record's CURRENT revision." resumeTillSession(id: ID!, revision: ID!, reason: String): TillSession! "Begin the closing count; requires the unrestricted capability + the record's CURRENT revision." beginCloseTillSession(id: ID!, revision: ID!, reason: String): TillSession! "Force-close a TillSession WITHOUT a proper count; requires the unrestricted capability + the record's CURRENT revision." forceCloseTillSession(id: ID!, revision: ID!, reason: String): TillSession! "Approve a pending ApprovalRequest: the approver's resolved tier rank must be ≥ requiredTier (AUTHZ/INSUFFICIENT) and the approver can NEVER be the requester (AUTHZ/SELF_APPROVAL — STRICT, no relaxation); a TTL-expired pending refuses CONFLICT/EXPIRED and lazily expires. Requires the unrestricted capability + the record's CURRENT revision. On approval the requester RETRIES the identical gated call — the retry consumes the approval by fingerprint." approveApprovalRequest(id: ID!, revision: ID!, reason: String): ApprovalRequest! "Deny a pending ApprovalRequest: the denier's resolved tier rank must be ≥ requiredTier (the face's forbidden form; detail carries the tiers); the fingerprint marker releases — the requester may mint a fresh request. Requires the unrestricted capability + the record's CURRENT revision." denyApprovalRequest(id: ID!, revision: ID!, reason: String): ApprovalRequest! "Cancel a pending ApprovalRequest; the fingerprint marker releases. Requires the unrestricted capability + the record's CURRENT revision." cancelApprovalRequest(id: ID!, revision: ID!, reason: String): ApprovalRequest! "Create an FxRate — the / splice insert; requires the unrestricted capability." createFxRate(input: NewFxRateInput!): FxRate! "Cancel a SCHEDULED FxRate window: allowed ONLY while the record is not yet effective (now < startAt). An effective or lapsed window is immutable rate history — CONFLICT/IMMUTABLE naming startAt vs now; supersede it with a new window instead. Requires the current revision (OCC) + the unrestricted capability; the record is kept, excluded from resolution (no-delete)." doomFxRate(id: ID!, revision: ID!, reason: String): FxRate! "Edit a FxRate's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateFxRate(id: ID!, revision: ID!, input: EditFxRateInput!): FxRate! "Create a Fulfillment; requires the unrestricted capability." createFulfillment(input: NewFulfillmentInput!): Fulfillment! "Start picking a pending Fulfillment: UNRESERVED (pos-channel) lines gate on AVAILABLE stock at the fulfilling LF — insufficient refuses CONFLICT/BACKORDER (retryable BY DESIGN: the fulfillment waits in pending; the identical retry passes once inbound stock lands); ecom lines already hold reserved claims and pass. Requires the unrestricted capability + the record’s CURRENT revision." startPickFulfillment(id: ID!, revision: ID!, reason: String): Fulfillment! "Pack a picking Fulfillment: stamps packedAt — the record becomes the Packing-List document node (the FF-… sysId is the document number; the immutable lines are the content). The verify_failed→CONFLICT/PACK_VERIFY form is -DORMANT (pack auto-passes until the pick/pack-verification policy builds). Requires the unrestricted capability + the CURRENT revision (OCC)." packFulfillment(id: ID!, revision: ID!, reason: String): Fulfillment! "Stage a packed pickup Fulfillment: the goods await handover at the LF; no stock moves until handover. Requires the unrestricted capability + the CURRENT revision (OCC)." stagePickupFulfillment(id: ID!, revision: ID!, reason: String): Fulfillment! "Hand over a staged pickup Fulfillment: ONE transaction relieves the claimed lines through the sell-relief lane (release of the ecom reserve rides it; COGS stamps at the current WMA), stamps the ORDER line fulfilledQty rollups + both delivery vectors, and — when the order is also fully paid — completes it (system:fully_paid_and_delivered). The capture seam is DECLARED-dormant. Requires the unrestricted capability + the CURRENT revision (OCC)." handoverFulfillment(id: ID!, revision: ID!, reason: String): Fulfillment! "Cancel a Fulfillment before ship/stage: un-stamps the Order’s fulfillmentClaimedQty claims (the order reservation STANDS — it is order-owned, released by cancelOrder); after ship/stage the reverse flow is a Return. Requires the unrestricted capability + the CURRENT revision (OCC)." cancelFulfillment(id: ID!, revision: ID!, reason: String): Fulfillment! "Authorize a created Payment: the CREATED-ZOMBIE REPAIR lane for an attempt whose applyTender request crashed between the mint and the ACK (the normal path drives this edge inside applyTender). Re-checks the order remainder live (a moved order refuses CONFLICT/OVER_TENDERED), fires the processor authorize POST-commit-style (never inside a transaction), and on the ACK commits the Tender row + the Order rollup stamp + this flip in ONE transaction. A decline refuses PAYMENT/AUTH_DECLINED (retryable — try another instrument) and the ultimate-failure edge lands the payment failed. Requires the unrestricted capability + the record's CURRENT revision." authorizePayment(id: ID!, revision: ID!, reason: String): Payment! "Capture an authorized Payment: the MANUAL REPAIR lane when an automatic delivery-instant capture failed loudly — the policy:delivered guard demands the parent order FULLY delivered (fulfillmentState fulfilled; CONFLICT/REF_STATE otherwise). The processor capture fires first (never inside a transaction); the ACK drives captured (+ succeeded when the processor reports settled — the two-edge cascade). Failure refuses PAYMENT/CAPTURE_FAILED (retryable; the payment stays authorized). Requires the unrestricted capability + the CURRENT revision (OCC)." capturePayment(id: ID!, revision: ID!, reason: String): Payment! "Cancel an authorized Payment: the order-cancel path's FIRST step (cancelOrder refuses CONFLICT/TENDERED while deposit money is held — release here, then cancel). The processor release fires first; the ACK commits the flip + a NEGATIVE reversal Tender row + the Order rollup stamp in ONE transaction. A captured payment refuses CONFLICT/IN_PROGRESS (money moved — the Refund lane is). Requires the unrestricted capability + the CURRENT revision (OCC)." cancelPayment(id: ID!, revision: ID!, reason: String): Payment! "Void an authorized Payment: the merchant voids the authorization — same release + reversal-tender shape as cancel (the flip + the NEGATIVE Tender row + the Order rollup stamp in ONE transaction), distinct terminal for the audit story. A captured payment has no void edge (FSM_TRANSITION_INVALID — settled money moves through Refunds). Requires the unrestricted capability + the CURRENT revision (OCC)." voidPayment(id: ID!, revision: ID!, reason: String): Payment! "Accept (concede) a Dispute: the processor close fires FIRST (POST /v1/disputes/:id/close — never inside a transaction; a processor refusal is CONFLICT/RECONCILE, retryable), then the flip commits. The withdrawn funds stay withdrawn — reports-only impact. Carries authority:manage_dispute. Requires the unrestricted capability + the record's CURRENT revision." acceptDispute(id: ID!, revision: ID!, reason: String): Dispute! "Create a Promotion in the caller's org group; requires the unrestricted capability." createPromotion(input: NewPromotionInput!): Promotion! "Deactivate a Promotion by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivatePromotion(id: ID!, revision: ID!, reason: String): Promotion! "Reactivate an inactive Promotion; requires the unrestricted capability + the record's CURRENT revision. Re-gated by the ACTIVE bound (at most 128 per group — VALIDATION/INVALID naming it)." reactivatePromotion(id: ID!, revision: ID!, reason: String): Promotion! "Doom (terminal) a Promotion by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. The referential-integrity guard blocks while NON-doomed trigger Coupons reference it (CONFLICT/REFERENCED naming first-8 — doom or re-point them first); deactivate stays FREE. NO doom-time enumeration of open orders (the RC-n write-time-only stance) — stored engine entries self-heal at the next recompute and PLACE re-validates." doomPromotion(id: ID!, revision: ID!, reason: String): Promotion! "Edit a Promotion's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePromotion(id: ID!, revision: ID!, input: EditPromotionInput!): Promotion! "Create a Coupon in the caller's org group; requires the unrestricted capability." createCoupon(input: NewCouponInput!): Coupon! "Deactivate a Coupon; requires the unrestricted capability + the CURRENT revision." deactivateCoupon(id: ID!, revision: ID!, reason: String): Coupon! "Reactivate a Coupon by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCoupon(id: ID!, revision: ID!, reason: String): Coupon! "Doom (terminal) a Coupon by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. Doom RELEASES the org-group code namespace (the next same-code create takes the marker over — reissuable, ≠ the SKU burn). NO doom-time enumeration of open orders holding the coupon — evaluation self-heals and PLACE refuses a dead coupon CONFLICT/REF_STATE." doomCoupon(id: ID!, revision: ID!, reason: String): Coupon! "Edit a Coupon's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCoupon(id: ID!, revision: ID!, input: EditCouponInput!): Coupon! "Create a StoredValueInstrument DIRECTLY in the caller's org group." createStoredValueInstrument(input: NewStoredValueInstrumentInput!): StoredValueInstrument! "Doom (terminal) a StoredValueInstrument by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. GATED by CONFLICT/BALANCE_OUTSTANDING while balanceMinor ≠ 0. The code marker stays BURNED forever." doomStoredValueInstrument(id: ID!, revision: ID!, reason: String): StoredValueInstrument! "Edit a StoredValueInstrument's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateStoredValueInstrument(id: ID!, revision: ID!, input: EditStoredValueInstrumentInput!): StoredValueInstrument! "Create a LoyaltyProgram in the caller's org group." createLoyaltyProgram(input: NewLoyaltyProgramInput!): LoyaltyProgram! "Deactivate a LoyaltyProgram by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateLoyaltyProgram(id: ID!, revision: ID!, reason: String): LoyaltyProgram! "Reactivate a LoyaltyProgram by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateLoyaltyProgram(id: ID!, revision: ID!, reason: String): LoyaltyProgram! "Doom (terminal) a LoyaltyProgram by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. -GATED by non-doomed LoyaltyMembers. Deactivate is the FREE pause — a paused program simply stops earning/redeeming at the next evaluation." doomLoyaltyProgram(id: ID!, revision: ID!, reason: String): LoyaltyProgram! "Edit a LoyaltyProgram's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateLoyaltyProgram(id: ID!, revision: ID!, input: EditLoyaltyProgramInput!): LoyaltyProgram! "ENROLL a LoyaltyMember into a program in the caller's org group." createLoyaltyMember(input: NewLoyaltyMemberInput!): LoyaltyMember! "Deactivate a LoyaltyMember by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateLoyaltyMember(id: ID!, revision: ID!, reason: String): LoyaltyMember! "Reactivate a LoyaltyMember by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateLoyaltyMember(id: ID!, revision: ID!, reason: String): LoyaltyMember! "Doom (terminal) a LoyaltyMember by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. GATED by CONFLICT/BALANCE_OUTSTANDING while pointsBalance ≠ 0. The identity marker STAYS on the corpse and the next same-email enrollment TAKES IT OVER (re-enrollable — the ≠-BURN contrast with instrument codes)." doomLoyaltyMember(id: ID!, revision: ID!, reason: String): LoyaltyMember! "Edit a LoyaltyMember's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateLoyaltyMember(id: ID!, revision: ID!, input: EditLoyaltyMemberInput!): LoyaltyMember! "Create a CustomerPriceGroup in the caller's org group." createCustomerPriceGroup(input: NewCustomerPriceGroupInput!): CustomerPriceGroup! "Deactivate a CustomerPriceGroup by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateCustomerPriceGroup(id: ID!, revision: ID!, reason: String): CustomerPriceGroup! "Reactivate a CustomerPriceGroup by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCustomerPriceGroup(id: ID!, revision: ID!, reason: String): CustomerPriceGroup! "Doom (terminal) a CustomerPriceGroup by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. -GATED by non-doomed LoyaltyMembers carrying the group. Deactivate is the FREE pause — a paused group's scoped promotions simply stop matching at the next evaluation." doomCustomerPriceGroup(id: ID!, revision: ID!, reason: String): CustomerPriceGroup! "Edit a CustomerPriceGroup's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied priceListId re-gates like create (in-tenant + ACTIVE + UNSCOPED); explicit null CLEARS it — the group plane goes silent." updateCustomerPriceGroup(id: ID!, revision: ID!, input: EditCustomerPriceGroupInput!): CustomerPriceGroup! "Create a MarkdownPlan in the caller's org group. The all-future/base/splice/cap gates run at SCHEDULE, not here." createMarkdownPlan(input: NewMarkdownPlanInput!): MarkdownPlan! "Edit a MarkdownPlan's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateMarkdownPlan(id: ID!, revision: ID!, input: EditMarkdownPlanInput!): MarkdownPlan! "Create a CommissionConfig in the caller's org group." createCommissionConfig(input: NewCommissionConfigInput!): CommissionConfig! "Deactivate a CommissionConfig by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateCommissionConfig(id: ID!, revision: ID!, reason: String): CommissionConfig! "Reactivate a CommissionConfig by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCommissionConfig(id: ID!, revision: ID!, reason: String): CommissionConfig! "Doom (terminal) a CommissionConfig by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed CG is immutable + never deleted. The optional reason rides the transition events." doomCommissionConfig(id: ID!, revision: ID!, reason: String): CommissionConfig! "Edit a CommissionConfig's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCommissionConfig(id: ID!, revision: ID!, input: EditCommissionConfigInput!): CommissionConfig! "Create an Affiliate in the caller's org group." createAffiliate(input: NewAffiliateInput!): Affiliate! "Deactivate a Affiliate by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateAffiliate(id: ID!, revision: ID!, reason: String): Affiliate! "Reactivate a Affiliate by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateAffiliate(id: ID!, revision: ID!, reason: String): Affiliate! "Doom (terminal) a Affiliate by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed AF is immutable + never deleted. The optional reason rides the transition events." doomAffiliate(id: ID!, revision: ID!, reason: String): Affiliate! "Edit a Affiliate's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied consumerId re-gates like create (same-group + not-doomed); explicit null UNLINKS the shopper — the ref-only link drops, attribution/earning unaffected." updateAffiliate(id: ID!, revision: ID!, input: EditAffiliateInput!): Affiliate! "Create a CorporateCustomer in the caller's org group; requires the unrestricted capability." createCorporateCustomer(input: NewCorporateCustomerInput!): CorporateCustomer! "Deactivate a CorporateCustomer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateCorporateCustomer(id: ID!, revision: ID!, reason: String): CorporateCustomer! "Reactivate a CorporateCustomer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateCorporateCustomer(id: ID!, revision: ID!, reason: String): CorporateCustomer! "Doom (terminal) a CorporateCustomer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed CorporateCustomer is immutable + never deleted. The optional reason rides the transition events." doomCorporateCustomer(id: ID!, revision: ID!, reason: String): CorporateCustomer! "Edit a CorporateCustomer's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCorporateCustomer(id: ID!, revision: ID!, input: EditCorporateCustomerInput!): CorporateCustomer! "Create an OrgCustomer selection — the per-org B2B selling ENABLEMENT of a group CorporateCustomer; requires the unrestricted capability." createOrgCustomer(input: NewOrgCustomerInput!): OrgCustomer! "Deactivate a OrgCustomer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgCustomer(id: ID!, revision: ID!, reason: String): OrgCustomer! "Reactivate a OrgCustomer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgCustomer(id: ID!, revision: ID!, reason: String): OrgCustomer! "Doom (terminal) a OrgCustomer by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgCustomer is immutable + never deleted. The optional reason rides the transition events." doomOrgCustomer(id: ID!, revision: ID!, reason: String): OrgCustomer! "Edit a OrgCustomer's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgCustomer(id: ID!, revision: ID!, input: EditOrgCustomerInput!): OrgCustomer! "Create a PriceList in the caller's org group." createPriceList(input: NewPriceListInput!): PriceList! "Deactivate a PriceList by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivatePriceList(id: ID!, revision: ID!, reason: String): PriceList! "Reactivate a PriceList by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivatePriceList(id: ID!, revision: ID!, reason: String): PriceList! "Doom (terminal) a PriceList by id, within the caller's org group; requires the unrestricted capability + the record's CURRENT revision. -GATED by non-doomed OrgCustomer/CustomerPriceGroup carriers; its OWN entries never block (they die with the plane at purge). Deactivate is the FREE pause — the plane simply falls through at the next capture." doomPriceList(id: ID!, revision: ID!, reason: String): PriceList! "Edit a PriceList's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePriceList(id: ID!, revision: ID!, input: EditPriceListInput!): PriceList! "Create a PriceListEntry — the splice insert." createPriceListEntry(input: NewPriceListEntryInput!): PriceListEntry! "Cancel a SCHEDULED PriceListEntry window: allowed ONLY while the record is not yet effective (now < startAt). An effective or lapsed window is immutable price history — CONFLICT/IMMUTABLE naming startAt vs now; supersede it with a new window instead. Requires the current revision (OCC) + the unrestricted capability; the record is kept, excluded from resolution (no-delete)." doomPriceListEntry(id: ID!, revision: ID!, reason: String): PriceListEntry! "Edit a PriceListEntry's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePriceListEntry(id: ID!, revision: ID!, input: EditPriceListEntryInput!): PriceListEntry! "Create a Consumer in the caller's org group; requires the unrestricted capability. ⚠ NO password argument — a staff-created Consumer has no self-service until resetConsumerPassword arms it (the separation; self-registration is consumerRegister)." createConsumer(input: NewConsumerInput!): Consumer! "Suspend a Consumer: active → suspended. The consumer's sessions are NOT revoked — they go INERT at their next resolve (the live-status gate) and restore on unsuspend within their deadlines. Requires the current revision (OCC) + the unrestricted capability." suspendConsumer(id: ID!, revision: ID!, reason: String): Consumer! "Release a Consumer's suspension: suspended → active. Still-live sessions resume working at their next resolve (the INERT-not-revoked law). Requires the current revision (OCC) + the unrestricted capability." unsuspendConsumer(id: ID!, revision: ID!, reason: String): Consumer! "Erase a Consumer: active|suspended → doomed, the DE-IDENTIFICATION terminal. The (group × email) identity marker BURNS within the group (the email does NOT re-register — ≠ the member/affiliate takeover); sessions go INERT at their next resolve; doomed drops from listings + search. v1 dooms the record + burns the marker; the PII scrub + PrivacyRequest register land. Requires the current revision (OCC) + the unrestricted capability; template class (privacy & compliance — hand-derived v19)." eraseConsumer(id: ID!, revision: ID!, reason: String): Consumer! "Edit a Consumer's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateConsumer(id: ID!, revision: ID!, input: EditConsumerInput!): Consumer! "Create a FROM-SCRATCH ConsentPurpose in the caller's org group. Canned baselines are copied via copyCannedConsentPurpose instead. Template class (privacy & compliance — hand-derived v20)." createConsentPurpose(input: NewConsentPurposeInput!): ConsentPurpose! "Retire a ConsentPurpose: active → inactive. Resolution DENIES over an inactive purpose, so retire is fail-safe BY CONSTRUCTION; standing ConsentRecords are untouched (proof preserved). The code marker HOLDS (the code stays occupied — reactivate restores it). Requires the current revision (OCC) + the unrestricted capability." deactivateConsentPurpose(id: ID!, revision: ID!, reason: String): ConsentPurpose! "Reactivate a ConsentPurpose by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateConsentPurpose(id: ID!, revision: ID!, reason: String): ConsentPurpose! "Doom (terminal) a ConsentPurpose: active|inactive → doomed. -GATED by the everReferenced write-once stamp — a purpose EVER named by a consent decision refuses CONFLICT/REFERENCED (detail names the ConsentRecord TYPE, id-less — the cardinality forbids listing walks; historical proof blocks forever, pre-purge; deactivate is the retire lane). A VIRGIN purpose dooms freely; its code marker RELEASES with the flip (reissuable — the org-code class). Requires the current revision (OCC) + the unrestricted capability." doomConsentPurpose(id: ID!, revision: ID!, reason: String): ConsentPurpose! "Edit a ConsentPurpose's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateConsentPurpose(id: ID!, revision: ID!, input: EditConsentPurposeInput!): ConsentPurpose! "Create a CsCase in the caller's org group. The consumer portal lane is openMyCase. Template class (ring & serve — cases are sales-floor work; hand-derived v21)." createCsCase(input: NewCsCaseInput!): CsCase! "Fire ONE declared caller transition on a CsCase: start · await_customer · resume · escalate · de_escalate · resolve · reopen_unresolved · close · cancel. Deny-by-default: an op whose edge is not declared FROM the case's current state refuses CONFLICT/FSM_TRANSITION_INVALID; resolve additionally REQUIRES the resolution block present. authority:cs guards ride start/close/cancel exactly; requires the unrestricted capability + the record's CURRENT revision. The optional reason rides the transition events. Template class with the cashier seat carved out (capture-tier keeps create/read/message only — hand-derived v21)." transitionCsCase(id: ID!, revision: ID!, op: CsCaseTransitionOp!, reason: String): CsCase! "Edit a CsCase's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCsCase(id: ID!, revision: ID!, input: EditCsCaseInput!): CsCase! "Create a GiftRegistry in the caller's org group. The consumer lane is createMyGiftRegistry. Template class (registry building is floor work — hand-derived v22)." createGiftRegistry(input: NewGiftRegistryInput!): GiftRegistry! "active → closed (authority:own_registry — on the staff lane authorization rides the channel + role templates; the owner closes via closeMyGiftRegistry). Fulfillments still record on a closed registry (ruling); item mutations refuse (the registry must be ACTIVE)." closeGiftRegistry(id: ID!, revision: ID!, reason: String): GiftRegistry! "closed|expired → doomed (authority:own_registry + referential_integrity — vacuous by design, subordinates are FAMILY [the CollectionMember class]; terminal ✦ immutable; drops from listings). Forbidden from active — close it or let it expire first." doomGiftRegistry(id: ID!, revision: ID!, reason: String): GiftRegistry! "Edit a GiftRegistry's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateGiftRegistry(id: ID!, revision: ID!, input: EditGiftRegistryInput!): GiftRegistry! "Fire ONE declared caller transition on a Review: approve (pending → approved) · publish (approved → published; the ratified failure form is VALIDATION/INVALID @1060) · reject (pending → rejected ✦) · remove (published|approved → removed ✦). Deny-by-default: an op whose edge is not declared FROM the review's current state refuses CONFLICT/FSM_TRANSITION_INVALID — pending → published is FORBIDDEN (moderation is never skippable, strict). Every edge is authority:moderate (the ratified table — ONE authz grain, the reason one mutation suffices); requires the unrestricted capability + the record's CURRENT revision. The optional reason rides the transition events. Template class (moderation = management judgment — manager/assoc_mgr only, hand-derived v22)." transitionReview(id: ID!, revision: ID!, op: ReviewTransitionOp!, reason: String): Review! "Open the caller's group's ONE TokenAccount. ⚠ Opening the wallet ARMS the metering (ruling — wallet existence IS the arm; the rater leg debits it). Requires the unrestricted capability. Template class A16_BILLING (hand-derived v23)." createTokenAccount(input: NewTokenAccountInput!): TokenAccount! "active → inactive (pause the wallet: purchases/grants refuse CONFLICT/REF_STATE while paused; the rater STILL debits — usage happened; root adjustment/transfer correction lanes stay live). Reversible." deactivateTokenAccount(id: ID!, revision: ID!, reason: String): TokenAccount! "inactive → active (resume purchases/grants)." reactivateTokenAccount(id: ID!, revision: ID!, reason: String): TokenAccount! "inactive → doomed (terminal ✦ immutable; the gate — the inbound-ref set is EMPTY by design, entries/purchases are FAMILY). ⚠ The singleton marker is PERMANENT (ruling): the group opens NO second wallet after doom — dooming the wallet permanently unbills the group (the metering arm disarms). Forbidden from active (deactivate first)." doomTokenAccount(id: ID!, revision: ID!, reason: String): TokenAccount! "Edit a TokenAccount's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTokenAccount(id: ID!, revision: ID!, input: EditTokenAccountInput!): TokenAccount! "Buy platform tokens for the caller's group: resolves the group's wallet via the singleton marker (no wallet → NOT_FOUND/CONSTRUCT: open the TokenAccount first; a PAUSED wallet refuses CONFLICT/REF_STATE), gates real money by classification × Stripe mode (ruling — live-mode requires a production group; test-mode legal always), resolves the volume tier + computes tokensPurchased SERVER-side, mints the platform TEST PaymentIntent with the ruling- join metadata BEFORE the record (PI-first — a processor refusal aborts with NOTHING written; an orphaned TEST intent is the deferral-14a reconcile class), then commits the record carrying the pi_… ref. Settlement is the WEBHOOK's (ruling — the existing 8-event roster; succeeded posts the purchase entry + balance atomically; failed/canceled settles failed). Requires the unrestricted capability. Template class A16_BILLING (hand-derived v23)." createTokenPurchase(input: NewTokenPurchaseInput!): TokenPurchase! "Create a Task in the caller's org group. Template class (internal work management — every staff tier files and works tasks; hand-derived v29)." createTask(input: NewTaskInput!): Task! "Fire ONE declared caller transition on a Task: start · unstart · complete · cancel · unpostpone. ⚠ postpone is the ONE bespoke exception — it carries its own returnAt argument, so it rides the postponeTask mutation (realized.bespokeTransitionOps). Deny-by-default: an op whose edge is not declared FROM the task's current state refuses CONFLICT/FSM_TRANSITION_INVALID; requires the unrestricted capability + the record's CURRENT revision. The optional reason rides the transition events — and on a note-minted task EVERY transition auto-appends ONE reply note under the origin root (the narrative law: the transition word + the reason verbatim, authored by the acting user; the scheduled return speaks as createdBy). Terminal transitions REMOVE the task's USER/TEAM book rows in the SAME txn (the inbox self-prunes); postpone prunes them too (parking means quiet — the REF row stays), and the return re-mints them. Template class (hand-derived v29)." transitionTask(id: ID!, revision: ID!, op: TaskTransitionOp!, reason: String): Task! "Edit a Task's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied reportTo re-gates like create (in-tenant + ACTIVE); explicit null CLEARS it — the task reports to nobody." updateTask(id: ID!, revision: ID!, input: EditTaskInput!): Task! "Create a Team in the caller's org group. Template class (org & group operational structure — team curation is management work; hand-derived v29)." createTeam(input: NewTeamInput!): Team! "active → inactive (retire the team from active use — reversible; its TASKBOOK#TEAM history stays readable)." deactivateTeam(id: ID!, revision: ID!, reason: String): Team! "inactive → active." reactivateTeam(id: ID!, revision: ID!, reason: String): Team! "active|inactive → doomed (terminal; refuses CONFLICT/REFERENCED while live tasks still name the team — the TASKBOOK#TEAM inbound-ref gate)." doomTeam(id: ID!, revision: ID!, reason: String): Team! "Edit a Team's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. A supplied leadUserId re-gates like create (in-tenant + ACTIVE + a member of the POST-edit team); explicit null CLEARS the lead — the standing lead-orphan refusal names this exact cure." updateTeam(id: ID!, revision: ID!, input: EditTeamInput!): Team! "Create a TaskLabel in the caller's org group. Template class (org & group operational structure — vocabulary curation is management work; hand-derived v29)." createTaskLabel(input: NewTaskLabelInput!): TaskLabel! "active → inactive (retire the label — reversible; tasks already carrying it keep it)." deactivateTaskLabel(id: ID!, revision: ID!, reason: String): TaskLabel! "inactive → active." reactivateTaskLabel(id: ID!, revision: ID!, reason: String): TaskLabel! "active|inactive → doomed (terminal; refuses CONFLICT/REFERENCED while live tasks still carry the label)." doomTaskLabel(id: ID!, revision: ID!, reason: String): TaskLabel! "Edit a TaskLabel's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTaskLabel(id: ID!, revision: ID!, input: EditTaskLabelInput!): TaskLabel! "active → suspended — the manager-imposed kill switch; instantly revocable via reactivate. Compose with revokeAllDeviceSessions to also kill the live sessions." suspendDevice(id: ID!, revision: ID!, reason: String): Device! "suspended → active (the kill-switch release)." reactivateDevice(id: ID!, revision: ID!, reason: String): Device! "pending_pairing|active|suspended → doomed (decommission — terminal; the hardware returns as a NEW enrollment). From active/suspended the gate refuses CONFLICT/REFERENCED while the paired Register has a LIVE TillSession (open/suspended/counting)." doomDevice(id: ID!, revision: ID!, reason: String): Device! "Edit a Device's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateDevice(id: ID!, revision: ID!, input: EditDeviceInput!): Device! "Create a DevicePeripheral on a Device. A card_reader+network create ALSO registers the smart reader with Stripe on the org's connected account. Template class A3_DEVICE (device fleet ops — manager+/owner G; hand-derived v30)." createDevicePeripheral(input: NewDevicePeripheralInput!): DevicePeripheral! "Deactivate a DevicePeripheral by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateDevicePeripheral(id: ID!, revision: ID!, reason: String): DevicePeripheral! "Reactivate a DevicePeripheral by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateDevicePeripheral(id: ID!, revision: ID!, reason: String): DevicePeripheral! "Doom (terminal) a DevicePeripheral by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed Peripheral is immutable + never deleted. The optional reason rides the transition events." doomDevicePeripheral(id: ID!, revision: ID!, reason: String): DevicePeripheral! "Edit a DevicePeripheral's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateDevicePeripheral(id: ID!, revision: ID!, input: EditDevicePeripheralInput!): DevicePeripheral! "active → doomed (terminal — the explicit revoke; authority:manage_apikey). The scheduled expiry needs no op; reach loss needs no op either (live-derivation — removing the minter’s ownership kills the key’s reach instantly)." doomApiKey(id: ID!, revision: ID!, reason: String): ApiKey! "Edit a ApiKey's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateApiKey(id: ID!, revision: ID!, input: EditApiKeyInput!): ApiKey! "Create a Scratchpad in the caller's org group. Template class (universal staff work — the Task row's class; hand-derived v66)." createScratchpad(input: NewScratchpadInput!): Scratchpad! "One caller edge of the spine FSM (ready · reopen · approve · abandon — the Task class; retry is EXCLUDED, carried by realizeScratchpad: a bare wire retry would strand realizing with no engine running). ready holds the plan for human review (refuses VALIDATION/INVALID on an empty plan); reopen returns it to draft for editing; approve PINS the plan revision (refuses VALIDATION/INVALID while ANY step is marked, and AUTHZ/FORBIDDEN when the APPROVER's own capability could not run every step — the preview≡enforcement pre-check, evaluated strict); abandon closes without (full) realization — constructs already born LIVE ON (born records are real; the stamps keep the provenance)." transitionScratchpad(id: ID!, revision: ID!, op: ScratchpadTransitionOp!, reason: String): Scratchpad! "Edit a Scratchpad's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateScratchpad(id: ID!, revision: ID!, input: EditScratchpadInput!): Scratchpad! "Decline an open Suggestion: the reason is REQUIRED (non-empty, ≤2000: the learning signal is the decline's whole purpose, so headless insists and every face mirrors) and is STORED on the record with the flip — Aldric's learning signal. Enforces the OFFER LAW (you can only decline what your own capability could run — AUTHZ/FORBIDDEN naming the steps otherwise) and the lazy expiry (a past-expiry open refuses CONFLICT/EXPIRED, expiring on the touch). Requires the unrestricted capability + the record's CURRENT revision. A declined finding never reopens — a changed condition mints a FRESH suggestion." declineSuggestion(id: ID!, revision: ID!, reason: String!): Suggestion! "One caller edge of the v2 schema FSM (park · reactivate · doom — the CsCase single-op class, A2_STRUCTURE owner-gated). park stops the generator for the org (the refresh engine skips parked schemas); reactivate resumes it; doom is the deliberate permanent kill — parked-first (active→doomed is documentedForbidden) and refused CONFLICT/REFERENCED while OPEN suggestions still cite the schema (close them first); a doomed schema never re-ensures. Requires the unrestricted capability + the record's CURRENT revision." transitionSuggestionSchema(id: ID!, revision: ID!, op: SuggestionSchemaTransitionOp!, reason: String): SuggestionSchema! "Create a Consultation in the caller's org group. Template class (universal staff work — the Scratchpad row's class)." createConsultation(input: NewConsultationInput!): Consultation! "One caller edge of the consultation FSM (archive · reopen · discard — the CsCase single-op class; the ruling). archive PARKS the record read-only (the consulted history stays listable; drafted plans remain takeable; the scheduler archives an idle conversation itself after 30 idle days, the reason on its history); reopen brings an archived conversation back to open (gated by the ≤10-open cap like a birth — the refusal names the cap and the cure); discard dooms it from open OR archived (lists drop; purge still owns deletion). The retired word close is refused typed. THE TURN TIER: 90 days after archiving the transcript moves to the archive bucket — consultationTurns reads it whole across the tier, a take then needs a reopen first, and reopen brings the rows back." transitionConsultation(id: ID!, revision: ID!, op: ConsultationTransitionOp!, reason: String): Consultation! "Edit a Consultation's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateConsultation(id: ID!, revision: ID!, input: EditConsultationInput!): Consultation! "Deactivate a WebhookSubscription by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." deactivateWebhookSubscription(id: ID!, revision: ID!, reason: String): WebhookSubscription! "inactive → active AND suspended → active (ONE op, two declared edges — the merchant repair flow: fix the target URL via update, then reactivate; reactivation clears suspendedAt + the failure counter and does NOT replay missed events — the receiver re-syncs via the API)." reactivateWebhookSubscription(id: ID!, revision: ID!, reason: String): WebhookSubscription! "active/inactive/suspended → doomed (terminal — gate-protected; the credential-store signing secret dies with it; authority:manage_integration)." doomWebhookSubscription(id: ID!, revision: ID!, reason: String): WebhookSubscription! "Edit a WebhookSubscription's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateWebhookSubscription(id: ID!, revision: ID!, input: EditWebhookSubscriptionInput!): WebhookSubscription! "Register a Plugin declaration; requires the unrestricted capability." createPlugin(input: NewPluginInput!): Plugin! "Deactivate a Plugin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivatePlugin(id: ID!, revision: ID!, reason: String): Plugin! "Reactivate a Plugin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivatePlugin(id: ID!, revision: ID!, reason: String): Plugin! "active/inactive → doomed (terminal — gate-protected SL-e: a NON-doomed OrgPlugin selection OR an un-doomed pluginId-bound WebhookSubscription refuses CONFLICT/REFERENCED naming the class; authority:manage_integration realizes as the template area)." doomPlugin(id: ID!, revision: ID!, reason: String): Plugin! "Edit a Plugin's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePlugin(id: ID!, revision: ID!, input: EditPluginInput!): Plugin! "Create an OrgPlugin selection — the per-org ENABLEMENT of a group Plugin; requires the unrestricted capability." createOrgPlugin(input: NewOrgPluginInput!): OrgPlugin! "Deactivate a OrgPlugin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateOrgPlugin(id: ID!, revision: ID!, reason: String): OrgPlugin! "Reactivate a OrgPlugin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateOrgPlugin(id: ID!, revision: ID!, reason: String): OrgPlugin! "Doom (terminal) a OrgPlugin by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed OrgPlugin is immutable + never deleted. The optional reason rides the transition events." doomOrgPlugin(id: ID!, revision: ID!, reason: String): OrgPlugin! "Edit a OrgPlugin's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateOrgPlugin(id: ID!, revision: ID!, input: EditOrgPluginInput!): OrgPlugin! "Deactivate a FeedSubscription by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." deactivateFeedSubscription(id: ID!, revision: ID!, reason: String): FeedSubscription! "inactive → active AND suspended → active (ONE op, two declared edges — the merchant repair flow: fix the feed via update, then reactivate; reactivation clears suspendedAt + the failure counter and does NOT run catch-up exports — the next run is the next cadence step)." reactivateFeedSubscription(id: ID!, revision: ID!, reason: String): FeedSubscription! "active/inactive/suspended → doomed (terminal — gate-protected; the FEEDREG registry row dies in the doom txn; the run objects reap with the tenant purge sweep; authority:manage_integration)." doomFeedSubscription(id: ID!, revision: ID!, reason: String): FeedSubscription! "Edit a FeedSubscription's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateFeedSubscription(id: ID!, revision: ID!, input: EditFeedSubscriptionInput!): FeedSubscription! "open → acknowledged (the merchant takes the alert under investigation — authority:review_fraud realizes as the A17_FRAUD template area; acknowledging DISARMS the scheduled age-out mechanically). Requires the record’s CURRENT revision." acknowledgeFraudAlert(id: ID!, revision: ID!, reason: String): FraudAlert! "acknowledged → confirmed (a CONFIRMED fraud finding — terminal + immutable but NOT doomed: the finding is a KEPT no-delete business record that stays listed). The optional reason lands on the revision cause — the disposition trail." confirmFraudAlert(id: ID!, revision: ID!, reason: String): FraudAlert! "acknowledged → dismissed (a FALSE POSITIVE — doomed terminal, drops from the listing; reachable by id + History). The reason is REQUIRED and lands on the revision cause." dismissFraudAlert(id: ID!, revision: ID!, reason: String!): FraudAlert! "Template class (privacy & compliance)." createPrivacyRequest(input: NewPrivacyRequestInput!): PrivacyRequest! "received → verified (the identity gate — v1 the verifier’s ASSERTION: the optional reason carries the proof method onto the revision cause; a mechanical proof gate is a named growth [the declared VALIDATION/IDENTITY failure form arrives with it]). authority:handle_privacy realizes as the template area." verifyPrivacyRequest(id: ID!, revision: ID!, reason: String): PrivacyRequest! "received/verified → rejected (ONE op, two declared edges — the doomed terminal: drops from the listing, reachable by id + History). The reason is REQUIRED and lands on the revision cause." rejectPrivacyRequest(id: ID!, revision: ID!, reason: String!): PrivacyRequest! "verified → in_progress (fulfillment underway via the EXISTING ops — eraseConsumer / exports / edits; the register never executes). received → in_progress is FORBIDDEN: no unverified fulfillment." startPrivacyRequest(id: ID!, revision: ID!, reason: String): PrivacyRequest! "Create a PolicyValueRecord — the splice insert (the FxRate recipe); requires the unrestricted capability. The tenant is stamped server-side; the scope anchor (organizationId XOR logicalFacilityId) is tenant-scoped server-side and must be ACTIVE (CONFLICT/REF_STATE otherwise); the key must be registry-defined with the value inside its bounds; an absent startAt = effective NOW (server-stamped); an explicit startAt in the past refuses (policy history is immutable fact); a start falling STRICTLY inside the immediately-preceding window of the (parent × key) sub-schedule auto-TRIMS that predecessor (revisioned + evented, cause policy-value-trim); overlap with ANY OTHER record refuses CONFLICT/POLICY_WINDOW_OVERLAP naming the blockers; the insert transaction rides the ANCHOR construct revision-bump companion (the serializer). Template class A18_POLICY (owner/manager — sensitive config)." createPolicyValueRecord(input: NewPolicyValueRecordInput!): PolicyValueRecord! "Cancel a SCHEDULED PolicyValueRecord window: allowed ONLY while the record is not yet effective (now < startAt). An effective or lapsed window is immutable policy history — CONFLICT/IMMUTABLE naming startAt vs now; supersede it with a new window instead. Requires the current revision (OCC) + the unrestricted capability; the record is kept, excluded from resolution (no-delete)." doomPolicyValueRecord(id: ID!, revision: ID!, reason: String): PolicyValueRecord! "Edit a PolicyValueRecord's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updatePolicyValueRecord(id: ID!, revision: ID!, input: EditPolicyValueRecordInput!): PolicyValueRecord! "Doom (terminal) a CouponBatch — VOIDS the unredeemed children (attach refuses naming the batch; their code markers stay owned until the family purges — batch codes are never reissued, the campaign identity law) while redeemed history stands untouched. The PARENT coupon is untouched. Requires the unrestricted capability + the CURRENT revision." doomCouponBatch(id: ID!, revision: ID!, reason: String): CouponBatch! "Create a Segment in the caller's org group; requires the unrestricted capability. static = explicit membership (addSegmentMembers fills it); dynamic REQUIRES a predicate (refs gated in-tenant + active; unknown tier names refuse teaching the program's ladder) and materializes membership at refreshSegment." createSegment(input: NewSegmentInput!): Segment! "Deactivate a Segment by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateSegment(id: ID!, revision: ID!, reason: String): Segment! "Reactivate a Segment by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateSegment(id: ID!, revision: ID!, reason: String): Segment! "Doom (terminal) a Segment — the definition dies; the membership rows reap with the family purge (never readable again). Requires the unrestricted capability + the CURRENT revision." doomSegment(id: ID!, revision: ID!, reason: String): Segment! "Edit a Segment's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateSegment(id: ID!, revision: ID!, input: EditSegmentInput!): Segment! "Create a Dashboard in the caller's org group; requires the unrestricted capability." createDashboard(input: NewDashboardInput!): Dashboard! "Deactivate a Dashboard by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateDashboard(id: ID!, revision: ID!, reason: String): Dashboard! "Reactivate a Dashboard by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateDashboard(id: ID!, revision: ID!, reason: String): Dashboard! "Doom (terminal) a Dashboard — a layout carries no referents, so doom is always free. Requires the unrestricted capability + the CURRENT revision." doomDashboard(id: ID!, revision: ID!, reason: String): Dashboard! "Edit a Dashboard's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateDashboard(id: ID!, revision: ID!, input: EditDashboardInput!): Dashboard! "Create a Report in the caller's org group; requires the unrestricted capability." createReport(input: NewReportInput!): Report! "Deactivate a Report by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateReport(id: ID!, revision: ID!, reason: String): Report! "Reactivate a Report by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateReport(id: ID!, revision: ID!, reason: String): Report! "Doom (terminal) a Report — a definition carries no referents, so doom is always free; a doomed report can no longer run. Requires the unrestricted capability + the CURRENT revision." doomReport(id: ID!, revision: ID!, reason: String): Report! "Edit a Report's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateReport(id: ID!, revision: ID!, input: EditReportInput!): Report! "Create a Collaborator in the caller's org group; requires the unrestricted capability. ⚠ NO password argument and NO invite in this response — issueCollaboratorInvite mints the show-once bootstrap token separately (the separation; the show-once secret is bespoke-op territory)." createCollaborator(input: NewCollaboratorInput!): Collaborator! "Deactivate a Collaborator: active → inactive. The collaborator's sessions are NOT revoked — they go INERT at their next resolve (the live-status gate re-reads the Collaborator every call) and restore on reactivate within their deadlines; an outstanding invite token stays stored but acceptCollaboratorInvite refuses on a non-active collaborator. Requires the current revision (OCC) + the unrestricted capability." deactivateCollaborator(id: ID!, revision: ID!, reason: String): Collaborator! "Release a Collaborator's admin pause: inactive → active. Still-live sessions resume working at their next resolve (the INERT-not-revoked law); an un-expired invite becomes acceptable again. Requires the current revision (OCC) + the unrestricted capability." reactivateCollaborator(id: ID!, revision: ID!, reason: String): Collaborator! "Erase a Collaborator: active|inactive → doomed, the DE-IDENTIFICATION terminal. The (group × email) identity marker BURNS within the group (the email does NOT re-register — re-invite as a NEW Collaborator); sessions go INERT at their next resolve; doomed drops from listings + search. v1 dooms the record + burns the marker; the PII scrub rides the ONE shared machinery (the Consumer posture VERBATIM — the erase failure form is EVENTED + retryable: CONFLICT/ERASE_FAILED). Requires the current revision (OCC) + the unrestricted capability; template class (privacy & compliance — the eraseConsumer class)." eraseCollaborator(id: ID!, revision: ID!, reason: String): Collaborator! "Edit a Collaborator's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateCollaborator(id: ID!, revision: ID!, input: EditCollaboratorInput!): Collaborator! "Create a SchedulableResource — a bookable staff/station/equipment entity at an LF; requires the unrestricted capability." createSchedulableResource(input: NewSchedulableResourceInput!): SchedulableResource! "Deactivate a SchedulableResource by id; requires the unrestricted capability + the record's CURRENT revision. The guard: a RESERVED booking (confirmed/in_progress Appointment — a live RESBOOK row) refuses CONFLICT/REFERENCED naming the appointments; requested Appointments never block (they refuse honestly at their own confirm). The optional reason rides the transition events." deactivateSchedulableResource(id: ID!, revision: ID!, reason: String): SchedulableResource! "Reactivate a SchedulableResource by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateSchedulableResource(id: ID!, revision: ID!, reason: String): SchedulableResource! "Doom a SchedulableResource by id; requires the unrestricted capability + the record's CURRENT revision (OCC). The guard: a RESERVED booking (confirmed/in_progress Appointment) refuses CONFLICT/REFERENCED naming the appointments — cancel/complete them first; requested Appointments never block. The optional reason rides the transition events." doomSchedulableResource(id: ID!, revision: ID!, reason: String): SchedulableResource! "Edit a SchedulableResource's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateSchedulableResource(id: ID!, revision: ID!, input: EditSchedulableResourceInput!): SchedulableResource! "Request an Appointment; requires the unrestricted capability." createAppointment(input: NewAppointmentInput!): Appointment! "Confirm a requested Appointment. ONE transaction writes the RESBOOK reservation rows + stamps noShowAt (= startAt + the appointment.no_show_window_minutes policy — the scheduler marks no_show at that instant). ⚠ The concurrent-confirm race window is the concurrent-online-sales class (disclosed — a serializing lock is a named growth). Requires the unrestricted capability + the record's CURRENT revision." confirmAppointment(id: ID!, revision: ID!, reason: String): Appointment! "Start a confirmed Appointment; requires the unrestricted capability + the record's CURRENT revision (OCC)." startAppointment(id: ID!, revision: ID!, reason: String): Appointment! "Cancel an Appointment before it starts; requires the unrestricted capability + the record's CURRENT revision (OCC)." cancelAppointment(id: ID!, revision: ID!, reason: String): Appointment! "Edit a Appointment's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision. The state ladder rules the fields (requested = all; confirmed/in_progress = caption/customer/orderId only — reschedule moves windows); terminals refuse CONFLICT/IMMUTABLE." updateAppointment(id: ID!, revision: ID!, input: EditAppointmentInput!): Appointment! "Create a Storefront — the ecom DTC publish-config under an Organization; requires the unrestricted capability. Publishing is a separate strict door." createStorefront(input: NewStorefrontInput!): Storefront! "Publish a DRAFT Storefront: THE INVALID_CONFIG GATE re-validates the WHOLE config record-aware (selling LF ACTIVE · theme ∈ the roster · collections ACTIVE · division ACTIVE + channel-kind · category ACTIVE — VALIDATION/INVALID naming the miss) AND the custom domain (when set) CLAIMS its GLOBAL uniqueness marker in the SAME transaction — CONFLICT/IDENTITY_TAKEN if another published site holds the name (cross-tenant blind: the refusal names nothing foreign). v1 provisions NO serving infrastructure (the map — this record is the control plane). Requires the unrestricted capability + the record's CURRENT revision." publishStorefront(id: ID!, revision: ID!, reason: String): Storefront! "Unpublish a PUBLISHED Storefront: the domain marker RELEASES in the SAME transaction (the name becomes claimable); the config keeps standing for a later republish. The ONLY road from published to doom runs through here (the FSM forbids published→doomed). Requires the unrestricted capability + the record's CURRENT revision (OCC)." unpublishStorefront(id: ID!, revision: ID!, reason: String): Storefront! "Republish an UNPUBLISHED Storefront: the SAME invalid_config gate re-runs record-aware AND the domain (when set) RE-CLAIMS its marker — another site may have taken the name since the unpublish (CONFLICT/IDENTITY_TAKEN). Requires the unrestricted capability + the record's CURRENT revision (OCC)." republishStorefront(id: ID!, revision: ID!, reason: String): Storefront! "Doom a draft/unpublished Storefront: a PUBLISHED site never dooms in one step — unpublish first (the domain releases there). gate-protected (nothing references a Storefront v1 — the guard stands armed for future referrers). Requires the unrestricted capability + the record's CURRENT revision (OCC)." doomStorefront(id: ID!, revision: ID!, reason: String): Storefront! "Edit a Storefront's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateStorefront(id: ID!, revision: ID!, input: EditStorefrontInput!): Storefront! "Create the AgentChannel of an Organization; requires the unrestricted capability. The tenant is stamped server-side; organizationId (the parent) is tenant-scoped server-side and must be ACTIVE; the selling location, pickup locations, collections, division, price list and excluded variants gate record-aware in the kit (each in-tenant; the LF/collections/division/price list ACTIVE; the division channel-kind; the price list selected for the owning organization and unscoped)." createAgentChannel(input: NewAgentChannelInput!): AgentChannel! "Publish a DRAFT AgentChannel: the completeness rule re-validates the WHOLE config record-aware (at least one Collection listed · at least one fulfillment method · ship backed by ship-to countries AND at least one shipping card whose countries are all ship-to countries · a pickup method backed by at least one pickup location · at least one ACTIVE allowed platform · every referenced record in-tenant and ACTIVE); a gap refuses VALIDATION/INVALID naming it. From live, the protocol doors serve the profile and answer agent platforms." publishAgentChannel(id: ID!, revision: ID!, reason: String): AgentChannel! "Pause a LIVE AgentChannel: the protocol doors answer unavailable with Retry-After and the profile hides checkout; the configuration stands for a later resume. The ONLY road from live to doom runs through here (a live channel never vanishes in one step)." pauseAgentChannel(id: ID!, revision: ID!, reason: String): AgentChannel! "Resume a PAUSED AgentChannel: the completeness rule re-runs record-aware (something referenced may have gone missing or inactive while paused — the resume refuses rather than serving a broken channel)." resumeAgentChannel(id: ID!, revision: ID!, reason: String): AgentChannel! "Doom a draft/paused AgentChannel: a LIVE channel never dooms in one step — pause first. The one-per-org marker RELEASES in the same transaction (the organization may create a fresh channel) and the private signing keys are reaped from the credential store (platforms still verifying with them must re-read the profile). gate-protected (nothing references an AgentChannel; the declared REFERENCED form stands armed)." doomAgentChannel(id: ID!, revision: ID!, reason: String): AgentChannel! "Edit a AgentChannel's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateAgentChannel(id: ID!, revision: ID!, input: EditAgentChannelInput!): AgentChannel! "Create a SizeRun in the caller's org group; requires the unrestricted capability. The fill is a READ (sizeRunFill: a total 0..1000000000 spread by the fill rule)." createSizeRun(input: NewSizeRunInput!): SizeRun! "Deactivate a SizeRun by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateSizeRun(id: ID!, revision: ID!, reason: String): SizeRun! "Reactivate a SizeRun by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateSizeRun(id: ID!, revision: ID!, reason: String): SizeRun! "Doom (terminal) a SizeRun by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards; a doomed SizeRun is immutable + never deleted. The optional reason rides the transition events." doomSizeRun(id: ID!, revision: ID!, reason: String): SizeRun! "Edit a SizeRun's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateSizeRun(id: ID!, revision: ID!, input: EditSizeRunInput!): SizeRun! "Create a TrainingRequirement in the caller's org group (🎓 — THE WIRE); requires the unrestricted capability and the training-manage right. courseKey must be a live play key (VALIDATION naming the courses otherwise); a second non-doomed rule for the same (roleTemplateKey, courseKey) refuses CONFLICT/IDENTITY_TAKEN; the org's rules are capped at 100 (CONFLICT/TRAINING_CAP)." createTrainingRequirement(input: NewTrainingRequirementInput!): TrainingRequirement! "Deactivate a TrainingRequirement by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the referential_integrity / authority / occ guards. The optional reason rides the transition events." deactivateTrainingRequirement(id: ID!, revision: ID!, reason: String): TrainingRequirement! "Reactivate a TrainingRequirement by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateTrainingRequirement(id: ID!, revision: ID!, reason: String): TrainingRequirement! "Doom (terminal) a TrainingRequirement (active|inactive→doomed) — certificates already issued stand; the rule simply stops binding anyone. Requires the unrestricted capability + the CURRENT revision." doomTrainingRequirement(id: ID!, revision: ID!, reason: String): TrainingRequirement! "Edit a TrainingRequirement's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTrainingRequirement(id: ID!, revision: ID!, input: EditTrainingRequirementInput!): TrainingRequirement! "Create a TrainingQuestion in the caller's org group (🎓 — THE WIRE); requires the unrestricted capability and the training-manage right. courseKey must be a live play key and stepN one of its steps (VALIDATION otherwise); a course's bank is capped at 60 non-doomed questions (CONFLICT/TRAINING_CAP). Born active — in the draw at once." createTrainingQuestion(input: NewTrainingQuestionInput!): TrainingQuestion! "Retire a TrainingQuestion from the draw (active→inactive) — kept, never asked, until reactivated; sittings already submitted keep their grades. Requires the unrestricted capability + the CURRENT revision." deactivateTrainingQuestion(id: ID!, revision: ID!, reason: String): TrainingQuestion! "Reactivate a TrainingQuestion by id; requires the unrestricted capability + the record's CURRENT revision. Deny-by-default + the authority / occ guards. The optional reason rides the transition events." reactivateTrainingQuestion(id: ID!, revision: ID!, reason: String): TrainingQuestion! "Doom (terminal) a TrainingQuestion (active|inactive→doomed) — it never returns to the draw; sittings that drew it keep their grades against the stored draw. Requires the unrestricted capability + the CURRENT revision." doomTrainingQuestion(id: ID!, revision: ID!, reason: String): TrainingQuestion! "Edit a TrainingQuestion's mutable attributes. Requires the unrestricted capability + the record's CURRENT revision." updateTrainingQuestion(id: ID!, revision: ID!, input: EditTrainingQuestionInput!): TrainingQuestion! }