Coastal Shipping 11 — Port & Terminal Electronic Interface (coast_11_portinterface)
Tell the port authority what the ship carries, and keep what the authority actually answered apart from whether the message got there — electronic manifest submissions, every transmission attempt, the authority's acknowledgments, corrections that amend an accepted submission without erasing it, terminal notices (external observations), reconciliation and deadlines.
Its central question:
The manifest was sent to the port — did the authority actually accept it, for this revision, and can we prove which cargo it accepted?
coast_11_portinterface is application SHP-11 of the Coastal Shipping series (coast_NN_<name>, numbered by the pack catalogue; each able to run stand-alone or as a network member, Stage 3). It shares no tables and no foreign keys with its siblings (for example coast_02_manifest, whose effective cargo it submits, or coast_06_voyage, whose port calls it names) — they link by canonical_ref strings and by messages. All data is fictional.
THE TRANSMISSION ADAPTER IS A SIMULATION. There is no real port, terminal or authority, no wire format, no endpoint, no credential and no authority schema anywhere in this application. A profile carries a mode (SIMULATION), a schema label (
mock_fixture_only) and, for a live profile that does not exist, a secret-store reference. A simulated acceptance is stored as simulated, published as modeSIMULATION, and confers nothing real: it cannot authorise a release, a sailing or a clearance.
The spine
PortInterfaceAuthority → PortInterfaceProfile → PortSubmission → SubmissionCargo / TransmissionAttempt / PortAcknowledgment / PortCorrection, with TerminalNotice, PortInterfaceReconciliation, TransmissionDeadline, PortInterfaceException, PortInterfaceAudit and PortInterfaceSnapshot around it.
The documents
| Page | What's in it |
|---|---|
| 00 — Overview | What the app is, transport vs acceptance, the rules, the 13 models, the demo scenario |
| 01 — Quick Reference | Menu map, every model, status vocabularies, the messages, how to run, seed and regenerate |
| 02 — System Diagram | The data model as diagrams (+ interactive viewer) and how the app links to its siblings |
Status
Built (handlers and workflow, tested): profile verification and activation (a LIVE profile is refused unless verified by one person, authorised by another and given a secret-store reference; none can be sent in this build); a submission prepared from the positive effective cargo of the manifest (never a reversal row; a DRAFT is prepared automatically when a manifest's effective cargo first arrives, if the profile's auto_prepare asks for it, and corrections are proposed with a replacement DRAFT when a newer revision arrives - nothing is ever sent without a person), validated against the current revision, the profile in force and the named load port call, approved by a supervisor who did not prepare it, sent through the simulated adapter (deadline checked, a late send needs a reason, no duplicate declaration, no resend while uncertain); the authority's response recorded apart from the transport result (accepted, rejected, partial and uncertain are different things; a conflicting, unauthentic, mismatching or unsolicited response is quarantined); corrections that keep the original, its attempts and its responses until the replacement is accepted; terminal notices as observations (validated, quarantined, never changing a movement or a tally); reconciliation with evidence by someone other than the sender; exceptions that close only when the domain correction is real; append-only attempts, responses and audit.
Scheduled (built, tested): portinterface.sweep_deadlines marks an overdue deadline and raises one exception, and makes a sent submission with no response in time UNCERTAIN (never resent).
Simulated, not real: transmission, authority responses, terminal notices, authenticity checks and the payload store (simulation-store:... labels, not stores). Not built: any live adapter, any real wire format or schema, signatures or replay protection of a real authority, real deadline rules.
Not enforced yet: the pack's "deadline per authority rule" is a date on a row (rule_version is a label); the call-completion obligation in coast_06_voyage (a call completes only with an accepted transmission) is that application's to enforce from the portinterface.submission_status event; assurance verification of closure is coast_16_assurance's.
The rules are in integration/rules.py, integration/exceptions.py, integration/engine.py and integration/handlers.py; the simulated adapter is integration/simulation.py; their tests are under server/tests/integration_apps/test_coast_11_*.
Translation decisions (pack → native DSL)
- 14 pack models: 12 translated, 2 dropped (S812
OutboxEvent, S813InboxMessage: the integration runtime provides them), 1 added (PortInterfaceException, the app's own control exception, asReleaseException) = 13. - Fleet-unique names:
PortInterfaceAuthority,PortInterfaceProfile,PortInterfaceReconciliation,PortInterfaceAudit,PortInterfaceSnapshot(packExternalAuthority,InterfaceProfile,InterfaceReconciliation,Audit,ExternalSnapshot); the rest keep the pack's names. canonical_id→canonical_ref;cidon the three network entities (PortSubmission,TerminalNotice,PortInterfaceException);version→version_no;source_event_id→source_event_sid; the pack'svoyage_ref,port_call_ref,manifest_refbecome*_canonical_ref+*_cid+*_ref(readable); dates are DateTime;nameadded to FK targets; enums upper case from the pack workflows (DRAFT … SUPERSEDED,RECEIVED,VALIDATED,QUARANTINED).- Added fields:
mode, the validating / approving / sending people and times,late_send_reason,simulated_transport_result(SIMULATION profiles only),approved_payload_hashonPortSubmission;status,authenticity,simulated,reported_ack_keyonPortAcknowledgment;notice_no,authenticity,simulated,reported_notice_key,quarantine_reasononTerminalNotice;live_enabled,credential_ref,ack_timeout_minutes,auto_prepare, verification and live-authorisation people on the profile;resolved_by/resolved_aton reconciliation. The pack's uniqueexternal_ack_key/external_notice_keyare kept: a conflicting repeat is stored under<key>~conflict~<hash8>with the key as sent inreported_*_key. - Event names:
shipping.portinterface.submission_status.v1→portinterface.submission_status,…terminal_notice.v1→portinterface.terminal_notice; the genericcontrol.exception_detected/assurance.action_completed→portinterface.exception_raised/portinterface.exception_resolved.submission_kindis the submission'smessage_kindin the event payload andobserved_atthe notice'soccurred_at, because those are envelope field names. - The pack gives SHP-11 no command;
portinterface.sweep_deadlines(orchestrator, scheduled) is added, asrelease.sweep_expiredwas. - The pack's
submission_statusis published only for ACCEPTED, REJECTED, UNCERTAIN, SUPERSEDED (the pack: "verified authority response only; transport sent is not acceptance"): SENT is never published. - A partial acknowledgment is not an acceptance: it rejects the submission as sent (status REJECTED, exception PARTIAL_ACKNOWLEDGMENT, reconciliation PARTIAL_ACK); a definite "not delivered" transport result is not simulated (a failed or unknown send is UNCERTAIN: the conservative reading of "reconcile before resubmitting").
- The notice quarantine exception has no control code (the pack's only SHP-11 control is PORT_SUBMISSION_UNCONFIRMED, for submissions).
Prototype system; draft. All names and data are fictional. Simulation only.