Skip to content

Source-only capability; no general automatic effect integration. The bounded Builder editorial composition now explicitly selects and composes it. The native use-case generator advertises supports_atomic_inbox_v1. Hosts must explicitly check that capability before supplying this spec to a generator; an older source or wheel may ignore unknown spec keys. No release or deployment is certified.

spec = {
"atomic_transition": True,
"principal_required": True,
"validate_inputs": True,
"typed_outcomes": True,
"transition": {"field": "status", "from": "draft", "to": "published"},
"writes": [{"field": "title", "source": "input.title"}],
"inbox_notification": {"title": "Post published", "body_field": "title"},
}
# UseCaseGenerator.generate("publish_post", fields_str="title:str", spec=spec)

The body field must be written from a required string input in the same conditional update. A pre-read-only field could become stale before the state CAS, so it is not admitted. The projected body must be UTF-8 storage text, without NUL, at most 4096 characters. The fixed title is nonempty storage text at most 120 characters. Arbitrary expressions, recipient fields and metadata mappings are not part of this spec. Other effects, related reads, counters and unfinished custom work are refused rather than silently composed.

The generated handler requires a host-supplied native InboxDeliveryChannel. The host binds its recipient email from deployment configuration and uses its real account store; there is no per-command recipient argument or fixture fallback. The handler prepares the pinned envelope before writing and uses <use_case>:v1:<aggregate UUID> as the effect key. Business metadata contains only aggregate_id, not the input object, credentials or private details.

The repository must advertise literal supports_transition_inbox_v1 = True and implement transition_inbox_if(..., inbox_message=...). It must return the committed delivery ID, not a truthy success sentinel. A missing capability, invalid body or unavailable recipient fails before the business write.

The Playground SQL repository reconciler now offers an explicit atomic_inbox=True opt-in. Its generated SQL class constructs the native SqlDeliveryStore on its own provider, using the native default notification_delivery_state table. It initializes schema outside the business transaction, then performs the conditional single-row update and queue insert inside that transaction. Enqueue failure rolls publication back. Ordinary transition methods remain unchanged. Cache wrappers and missing transitions are refused; no nested transaction or independently committing queue is substituted. This reconciler option is not yet selected by the graph planner/writer.

Success reports data.notification = "queued" and data.delivery_id; it never claims delivery. A post-commit native dispatcher/worker using the same persisted queue performs delivery, with native backoff, leases and inbox receipt dedup. Do not repeat publication to recover an already committed delivery intent. See the native inbox contract for pinned-account behavior, failure/recovery and retention boundaries.

apps/playground/backend/tests/unit/gen/test_use_case_atomic_inbox.py imports actual generated handler and SQL repository modules. It uses real SQLite and SQL accounts, trigger-induced enqueue rejection, a fresh provider/store/channel connection and the native worker. It verifies state/queue atomicity, persisted recipient/effect identity, no intent from failed publication, sequential conflict, missing principal/recipient/capability, invalid body and unpinned/non-inbox rejection. SDK tests cover closed spec vocabulary, unsupported compositions and fail-before-write behavior including dry runs.

Fresh checks: 690 tests across native Events CLI generation and the two transition repository suites; a separate 580 tests across Notification/example and selected Builder graph/authentication/publication boundaries. Three legacy emission variants were also compared byte-for-byte against the pre-change template. Configured mypy passes the four changed/new source modules; Ruff passes the changed source/tests. These are local CPython3.11/SQLite checks, not HTTP authentication, PostgreSQL, process-kill crash testing, production or owner/security acceptance.

Still required: explicit graph selection and fresh-tree/dependency gating, trusted HTTP principal/permission enforcement, application DI/worker/operator binding, authenticated inbox mounting, and a fully generated editorial TCP proof. No auth/event/effect gate has been loosened by this primitive. Existing public anonymous actions cannot select it, and the original separate Notification Center host is not being copied into a generated project or treated as graph output.