Stateful journeys/Capture & Feedback
statefulplace contribution aggregate

Governed place contribution and publication

Embed the credential-free Add a Place surface, record what the user reports, reconcile independently, and call a place published only when durable provider-backed evidence exists.

Every state means something operational

A state is not a UI label. It determines which actor may act, what evidence exists, what may be retried, and how recovery proceeds.

01
draft

Draft

The host owns a bounded contribution intent, business purpose, and external identity before any provider surface opens.

02
widget_open

Widget open

The Mappls-hosted form is visible for one recorded attempt, while provider UI and submission remain outside the host contract.

03
submission_reported

Submission reported

The contributor says the hosted form showed success, which is useful testimony but not a receipt or publication result.

04
publication_pending

Publication pending

An operations process is checking supported Mappls search or an approved provider receipt for a stable published identity.

05
publishedterminal

Published

A supported provider surface returned a six-character Mappls Pin with attributable observation evidence.

06
rejected

Rejected

A reviewer found a duplicate, invalid, unsafe, or otherwise non-publishable contribution and recorded why.

07
withdrawnterminal

Withdrawn

The host stopped its own follow-up workflow at the contributor's request without claiming that the provider submission was deleted.

Transitions are attributable and retry-safe

Commands express intent. The aggregate validates current state and invariants, commits one new version, and emits a fact in the same transaction.

Command & actorAllowed fromResultIdempotency strategy
create_contributionHost application
new aggregate
draftplace_contribution.created

Map one bounded external case identity to one aggregate across network retries.

open_widgetContributor
draft
widget_openplace_contribution.widget_opened

Create at most one immutable attempt per command key and aggregate version.

report_submissionContributor
widget_open
submission_reportedplace_contribution.submission_reported

Record one acknowledgement for the active attempt without inventing a provider receipt.

queue_reconciliationHost application
submission_reported
publication_pendingplace_contribution.reconciliation_queued

The same scheduling key creates at most one pending transition and outbox event.

confirm_publicationOperations reviewer
submission_reportedpublication_pending
publishedplace_contribution.published

Hash the supported evidence source, Mappls Pin, observation time, and source fingerprint before committing.

rejectOperations reviewer
submission_reportedpublication_pending
rejectedplace_contribution.rejected

Preserve the review decision, reason, and attempt version under the reviewer command key.

retryContributor
rejected
widget_openplace_contribution.retried

Create a new immutable attempt once while retaining the rejected attempt and decision in audit history.

withdrawContributor
draftwidget_opensubmission_reportedpublication_pending
withdrawnplace_contribution.withdrawn

Stop host follow-up once without representing this as provider-side deletion.

Persist enough to recover and explain

Keep provider responses, business identity, state, events, and side-effect delivery distinct so each can be reconciled safely.

Contribution aggregate

Current host-owned state, business identity, purpose, ownership, and optimistic version.

contributionIdexternalIdstateversionpurposeowner

Widget attempt

Immutable record of each frame launch and contributor-reported outcome without provider-internal data.

attemptIdaggregateVersionopenedAtreportedAtdocumentedSourceUrl

Publication evidence

Attributable supported-source proof that a stable Mappls identity is observable.

mapplsPinevidenceSourceobservedAtsourceFingerprintreviewer

Audit and outbox

Append-only transitions and exactly-once-in-effect downstream notifications.

eventIdaggregateVersionactoridempotencyKeyoutboxStatus

Protect truth at the aggregate boundary

  1. 1

    A hosted success screen or contributor report never proves publication.

  2. 2

    No callback, browser message, receipt, moderation status, or withdrawal capability is invented when the public source does not document it.

  3. 3

    Only provider-backed evidence containing a valid Mappls Pin can close the aggregate as published.

  4. 4

    Every widget attempt is immutable and linked to the aggregate version that opened it.

  5. 5

    Commands are idempotent, compare expected version, and commit audit plus outbox atomically.

  6. 6

    Contribution text, actor identity, and precise location follow declared purpose, access, and retention boundaries.

Know what to do before it breaks

Recovery changes durable truth only through the same rules as normal operation. A timeout is an unknown outcome, not evidence that nothing happened.

Hosted frame is blocked or unavailable

Detect

The host cannot load the established HTTPS source within its timeout and CSP boundary.

Recover

Keep the contribution in draft, explain the boundary, and offer an external open or later retry without claiming a submission.

User loses the success acknowledgement

Detect

No provider receipt exists and the contributor cannot confirm what the hosted surface showed.

Recover

Leave the attempt unresolved and allow a deliberate new attempt; never infer completion from iframe navigation.

Reconciliation finds an existing duplicate

Detect

Supported search resolves the same place identity or a reviewer establishes duplicate ownership.

Recover

Reject with duplicate reason and link the known Mappls Pin as context, not as evidence that this attempt created it.

No public result appears within the operating window

Detect

Every bounded supported-source check returns no qualifying Mappls identity before the stated review deadline.

Recover

Keep pending or reject according to published host policy and expose the last check time without promising a provider SLA.

Application restarts during review

Detect

An in-flight command lacks acknowledgement while aggregate, command key, and outbox state are durable.

Recover

Reload the aggregate and replay the same command key; do not duplicate an attempt, decision, or notification.

Observe the journey, not merely HTTP status

Measure state age, event health, retries, reconciliation, and sensitive-data access alongside latency and error rate.

  • Widget opens, contributor reports, and abandonment by attempt
  • Time from report to first reconciliation and terminal decision
  • Pending age and last supported-source check
  • Publication evidence source and Mappls Pin validity
  • Duplicate and rejection reasons without opaque provider payloads
  • Withdrawal count explicitly separated from provider-side deletion
  • Idempotency replay and optimistic version conflict rate
  • Outbox backlog, retry, and dead-letter age

Contracts, repositories, workshops, tutorials, and runnable evidence

Only explicitly indexed evidence is linked. Empty sections are not backfilled with invented endpoints or package names.