{"spec":"AIP-BS-MULTI-SITE-CONFORMANCE","version":"2026-10-03","standard":"multi-site-conformance-build-standard","source":"https://aipathway.com.au/explore-ai/multi-site-conformance-build-standard","markdown":"https://aipathway.com.au/explore-ai/multi-site-conformance-build-standard.md","licence":"CC BY 4.0","how_to_read":"Nine of these eleven checks run on your own machine, against the stub, before you talk to anybody. The last one is a live tenant, and that one runs against your own live systems. One is not a software check at all: it asks what you measured before you started.","verdicts":{"pass":"asserted green here","fail":"asserted red here. This is a fixture: it names the check to price","shape_only":"shape holds on the stub, truth needs the live provider","with_us":"cannot be proved on the stub; runs against your own live systems (see with_us_next)","evidence_required":"not a software check. Attach what proves it"},"tally":{"total":11,"onStub":9,"productionOnly":1,"partial":0,"preconditions":1},"envelope_version":"1.0","port_shape":{"read_ledger":{"verb":"read","subject":"ledger"},"read_job":{"verb":"read","subject":"job"},"read_asset":{"verb":"read","subject":"asset"},"read_rule":{"verb":"read","subject":"rule"},"read_contacts":{"verb":"read","subject":"contacts"},"read_segment":{"verb":"read","subject":"segment"},"resolve_address":{"verb":"read","subject":"address"},"write_job":{"verb":"write","subject":"job"},"read_pricebook":{"verb":"read","subject":"pricebook"},"draft_quote":{"verb":"write","subject":"quote"},"write_invoice":{"verb":"write","subject":"invoice"},"write_ledger":{"verb":"write","subject":"ledger"},"record_promise":{"verb":"write","subject":"promise"},"record_service":{"verb":"write","subject":"service_record"},"release_payment":{"verb":"write","subject":"payment"},"talk":{"verb":"say","subject":"turn"},"disclose":{"verb":"say","subject":"disclosure"},"send_sms":{"verb":"say","subject":"sms"},"notify":{"verb":"say","subject":"alert"},"escalate":{"verb":"say","subject":"handoff"},"issue_notice":{"verb":"say","subject":"notice"},"answer":{"verb":"say","subject":"answer"},"publish_report":{"verb":"say","subject":"report"},"record_consent":{"verb":"write","subject":"consent"},"read_file":{"verb":"read","subject":"file"},"write_file":{"verb":"write","subject":"file"},"raise_task":{"verb":"write","subject":"task"},"read_node":{"verb":"read","subject":"node"},"write_node":{"verb":"write","subject":"node"},"read_register":{"verb":"read","subject":"register"},"write_register":{"verb":"write","subject":"register"},"index_passage":{"verb":"attach","subject":"passage"},"search_index":{"verb":"read","subject":"index"},"read_inbox":{"verb":"read","subject":"message"},"file_message":{"verb":"attach","subject":"message"},"write_order":{"verb":"write","subject":"order"},"read_quote":{"verb":"read","subject":"quote"},"write_log":{"verb":"write","subject":"log"},"evidence":{"verb":"attach","subject":"evidence"},"cite":{"verb":"attach","subject":"citation"},"rank":{"verb":"decide","subject":"order"},"gate":{"verb":"decide","subject":"gate"}},"provider":{"boundary":{"never":["treat training material as a control","compute the score twice","invent a key"],"stays_with_person":["accepting a local variation as legitimate, and recording why","changing the key contract, which is a version bump and not an edit","every conversation with a segment that has crossed a threshold","judging whether a low score is a compliance problem","deciding a new segment is ready to take real records"]},"job":"one operating standard across many sites","skill":"multi-site-conformance","stub":"local.mock_sites","production":null,"product":null,"insert":null,"with_us":{"kind":"own_systems","note":"No hosted step. The production check runs over the sites' own key contract and evidence."}},"with_us_next":"No hosted step. The production check runs over the sites' own key contract and evidence. There is nothing to buy: your build does this step on the business's own systems. No production run is offered yet, because the live port map is not published, so do not run AIPATHWAY_ENV=production. Run the pass test by hand on the real systems and attach the evidence.","default_path":null,"boundary":{"never":["treat training material as a control","compute the score twice","invent a key"],"stays_with_person":["accepting a local variation as legitimate, and recording why","changing the key contract, which is a version bump and not an edit","every conversation with a segment that has crossed a threshold","judging whether a low score is a compliance problem","deciding a new segment is ready to take real records"]},"substrate":{"how_to_read":"These are roles, not products. Work out which you already have by matching `providers[].detect` against the repository, then build or add only the gap. No check asserts against a vendor, so any substrate that answers the role passes the same checks.","requires":[{"role":"record","label":"Somewhere the book lives","need":"Durable storage that the workflow owns the write path to, keyed so the same record can be found twice.","when_missing":"Half a day. Any Postgres will do and the free tiers are ample at this size. The trap is not the database, it is letting people edit around the app that is supposed to own the value.","ports":["read_rule","read_segment"]},{"role":"schedule","label":"Something that runs it on time","need":"A trigger that fires on a cadence and can call an authenticated endpoint.","when_missing":"An hour. Expose one authenticated endpoint that starts the work and let anything call it, so the schedule is never welded to whoever is hosting you.","ports":["gate"]},{"role":"send","label":"Something that sends","need":"Email or SMS from a domain the recipient recognises, with delivery visible enough to tell a bounce from a silence.","when_missing":"An hour for the wiring, longer for the DNS. Sending from a domain you do not own is the single fastest way into a spam folder.","ports":["notify"]},{"role":"surface","label":"Something a person opens","need":"A view of the book that whoever does this job can read and act on without asking a developer.","when_missing":"Start at tier 0 and stop there until the business asks for more. The cheapest surface is not a screen, it is a scheduled email carrying the list, and for one person doing this job that is not a compromise, it is the right answer. On Microsoft 365 or Workspace you can skip straight past this: a list and a sheet are already what people open. Build upward only when two people need the same list at the same time.","tiers":[{"tier":0,"label":"A scheduled digest carrying the list","cost":"About an hour. Needs nothing you do not already have.","satisfiedBy":"send","whenYouNeedIt":"One person does this job. They want to know what is waiting when they sit down, and they act on it from their inbox."},{"tier":1,"label":"A read-only page showing the book","cost":"An afternoon. One query and one table.","whenYouNeedIt":"Somebody needs to look mid-day without waiting for tomorrow's digest, or to answer a customer on the phone."},{"tier":2,"label":"Editable rows, a queue and a log","cost":"A day or two with a coding agent, which is what agents are best at. It is bounded work: the fields are the schema, the queue is whatever escalate hands off, the log is the trace.","whenYouNeedIt":"More than one person shares the book and they need to correct it without treading on each other, and you need to see afterwards who changed what."}],"already_reachable":[{"tier":0,"label":"A scheduled digest carrying the list","because":"this standard already requires the send role, so nothing new is needed for it"}],"ports":["escalate","publish_report"]}],"registry":"https://aipathway.com.au/substrates.json"},"checks":[{"id":"key-contract-versioned","n":1,"title":"The key contract is written down and versioned","statement":"Not an unwritten convention or a diagram in an onboarding deck.","assertable":"stub","ports":["read_rule"],"stimulus":"A request for the key contract currently in force.","assertion":"It is returned as a versioned document. A convention that exists only in the shape of the data fails."},{"id":"segments-add-not-fork","n":2,"title":"Segments can add fields and cannot rename or fork keys","statement":"Enforced by validation, not by asking.","assertable":"stub","ports":["read_segment","gate"],"stimulus":"One segment adding a field, one renaming a key, one introducing a second key for the same thing.","assertion":"The addition is accepted. Both the rename and the fork are refused at validation, not flagged in a report afterwards."},{"id":"membership-from-access-group","n":3,"title":"Segment membership comes from an access group","statement":"Not a label somebody types into a record or a report.","assertable":"stub","ports":["read_segment"],"stimulus":"A record whose typed segment label disagrees with its access group.","assertion":"The access group decides. A build that trusts the typed label fails, because that label is how segments drift in the first place."},{"id":"drift-detected-all-four-kinds","n":4,"title":"Drift is detected on a schedule, covering all four kinds","statement":"Including the two that look like a quiet branch.","assertable":"stub","ports":["read_segment","gate"],"stimulus":"One segment seeded with each of the four kinds of drift, and the clock advanced to the scheduled run.","assertion":"All four are detected. Detecting only the loud two is the common partial build and it fails here."},{"id":"one-definition-per-measure","n":5,"title":"One definition of every measure, computed once","statement":"No segment can produce its own version of the same number.","assertable":"stub","ports":["publish_report","read_rule"],"stimulus":"Two segments asked for the same measure over the same underlying records.","assertion":"Both receive the same number from one computation. Two computations that happen to agree today still fail."},{"id":"report-publishes-regardless","n":6,"title":"The report publishes on schedule regardless of the numbers","statement":"Its absence never becomes the signal.","assertable":"stub","ports":["publish_report"],"stimulus":"A scheduled run in a period where nothing drifted and nothing breached.","assertion":"The report still publishes, saying so. A build that suppresses an all-clear fails, because silence then means both 'fine' and 'stopped'."},{"id":"each-segment-sees-its-own","n":7,"title":"Each segment sees its own report","statement":"Not only the centre. Same findings, same detail.","assertable":"stub","ports":["publish_report","read_segment"],"stimulus":"A run producing findings for two segments.","assertion":"Each segment can read its own findings at the same detail the centre sees. A centre-only report fails."},{"id":"threshold-routes-to-a-person","n":8,"title":"A threshold routes to a named person","statement":"Not to an all-branch email.","assertable":"stub","ports":["escalate","notify"],"stimulus":"A breach crossing a routing threshold.","assertion":"It routes to a named person. A distribution list fails, because nobody on it owns the item."},{"id":"gates-live-before-first-record","n":9,"title":"A new segment's gates are live before its first real record","statement":"Onboarding does not start with drift already in the data.","assertable":"stub","ports":["read_segment","gate"],"stimulus":"A new segment created, then a record written to it immediately.","assertion":"The record is validated against the contract. A segment that accepts records before its gates are live fails."},{"id":"survives-the-builder","n":10,"title":"It survives the builder","statement":"Someone other than the builder can explain what it does, and it runs on an account the business owns.","assertable":"precondition","ports":["read_rule"],"stimulus":"No stimulus. The builder names who else can explain it and whose account the contract and the checks runs on.","assertion":"The runner reports what was declared and never scores it green on its own say-so.","stubLimit":"Not a runtime property. Software cannot prove a second person understands it, and outliving its author is precisely what is being asked about."},{"id":"pass-test","n":11,"title":"The pass test passes","statement":"Break one segment's contract and bypass a gate, and both appear in that segment's own report; rename a key and validation refuses it; let a period pass with nothing to report and the report still publishes on time.","assertable":"production","ports":["read_segment","gate","publish_report"],"stimulus":"In a live segment: a record missing a required key or holding an off-list value, a gate bypass (a typed date or work closed without evidence), a real rename attempt, and a real quiet period.","assertion":"Both findings appear in that segment's own report at the next scheduled run, the rename is refused at the source, and the all-clear publishes on time.","stubLimit":"Deliberately unpassable on a stub. A stub segment does what you tell it; a real one is run by people who will rename a column on a Tuesday for a good local reason."}]}