Fix signup registration receipts and activation worker lifetime (#57)
This commit is contained in:
1 parent
bd675357bb
commit
abca15f047
6 files changed
+148
-13
No files matched your search
+57
-4
@@ -5,6 +5,58 @@ Task [#46](https://git.sendico.io/tech/sxchnge/issues/46), branch
|
||||
customer creation, runtime, shared database source and Flutter error feedback.
|
||||
Delivery: [PR #47](https://git.sendico.io/tech/sxchnge/pulls/47), targeting `main`.
|
||||
|
||||
## Registration response correction
|
||||
|
||||
Follow-up [#57](https://git.sendico.io/tech/sxchnge/issues/57), branch
|
||||
`identity-facts-57`, corrects the registration success status to HTTP 201 Created.
|
||||
Sendico's individual creation handler returns 201; the original adapter and test
|
||||
fixture incorrectly required 200. A successful registration therefore left a
|
||||
pending customer with an unresolved claim and `signup_attention_required`.
|
||||
The adapter now checks the exact status per operation before validating receipts:
|
||||
201 for registration and 200 for Facts intake. Other statuses, including other
|
||||
2xx responses, remain failures. Malformed receipts and uncertain registrations
|
||||
still require the existing recovery rules.
|
||||
|
||||
On 2026-10-17, the affected local signup was reconciled using its registration
|
||||
correlation in Sendico logs and an authenticated organization-scoped individual
|
||||
GET. A conditional majority write bound that confirmed individual to the existing
|
||||
local claim, preserving the saved facts, namespace and registration request.
|
||||
The rebuilt BFF resumed the public activation-resend flow: Facts intake returned
|
||||
a persisted receipt and the endpoint returned 202 after activation-email queue
|
||||
acceptance. No replacement individual was registered. The account remains
|
||||
pending until the customer confirms the email; queue acceptance does not prove
|
||||
inbox delivery.
|
||||
|
||||
Recovery also exposed a notification worker lifetime issue: its NATS subscription
|
||||
retained the 20-second startup context and was automatically unsubscribed after
|
||||
that deadline. Resource provisioning now has its own bounded context, while the
|
||||
subscription follows the service lifetime and closes at shutdown. A regression
|
||||
test checks that releasing provisioning leaves the subscription context active,
|
||||
and service cancellation still ends it.
|
||||
|
||||
The rebuilt worker processed the queued activation message. The live Resend
|
||||
provider rejected it with `provider_authentication_failed` (HTTP 401 or 403),
|
||||
leaving delivery in `failed` after one attempt. The configured API key/sender
|
||||
authorization must be corrected before sending another activation email. Rotate
|
||||
the credential securely with `make email`, wait for Vault Agent to refresh it,
|
||||
restart notifications so it reloads its environment, then use activation resend
|
||||
with a new idempotency key. Do not replay the failed notification as a success or
|
||||
mark the customer active on their behalf.
|
||||
|
||||
Validation passed: `GOFLAGS=-p=2 make test` (all backend race tests and canonical
|
||||
frontend suites), `make lint-backend`, focused provider/identity race tests and
|
||||
notification bus/app race tests. The HTTP 201 regression first failed against the
|
||||
old adapter and passed after correction. An earlier full run hit a database
|
||||
credential-rotation timing failure at `rotation_test.go:249` during the Docker
|
||||
build; the isolated race-test retry and both subsequent full runs passed.
|
||||
Local BFF and notifications images were rebuilt with fresh upstream manifests
|
||||
and resolved stable digest pins; the BFF, session sidecar and notifications
|
||||
services are healthy. NATS shows the worker still waiting for deliveries beyond
|
||||
the startup deadline, with no pending or unacknowledged jobs. Live email delivery
|
||||
is blocked by provider authorization as described above. No security scans were
|
||||
requested or run. Unrelated notifications runtime settings are excluded from
|
||||
the task commits.
|
||||
|
||||
## Behavior and boundaries
|
||||
|
||||
With `api.sendico` configured, the product BFF creates the local pending customer
|
||||
@@ -18,7 +70,7 @@ backfilled or blocked at login.
|
||||
|
||||
The adapter consumes these existing Sendico contracts:
|
||||
|
||||
- `POST /individuals/{organization_ref}`, empty body, HTTP 200 registration
|
||||
- `POST /individuals/{organization_ref}`, empty body, HTTP 201 registration
|
||||
receipt containing `subject_ref` and `registered_at`.
|
||||
- `POST /identity_facts/{organization_ref}`, HTTP 200 immutable intake receipt
|
||||
containing `submission_ref`, `subject_ref` and `accepted_at`.
|
||||
@@ -73,9 +125,10 @@ the adapter rereads it on every request. Startup rejects missing, expired or
|
||||
mismatched credentials and rejects Sendico configuration without notifications.
|
||||
|
||||
HTTPS is required except for loopback HTTP test/development endpoints. Redirects
|
||||
are rejected and each HTTP call has a four-second timeout. Non-200 responses,
|
||||
malformed/truncated receipts, invalid identifiers, wrong subjects and unsuccessful
|
||||
envelopes never count as acceptance. Upstream error bodies are not surfaced.
|
||||
are rejected and each HTTP call has a four-second timeout. Unexpected response
|
||||
statuses (registration requires 201; Facts intake requires 200), malformed/truncated
|
||||
receipts, invalid identifiers, wrong subjects and unsuccessful envelopes never
|
||||
count as acceptance. Upstream error bodies are not surfaced.
|
||||
|
||||
Omitting `api.sendico` keeps existing local-only behavior. Enabling it also gates
|
||||
activation for previously pending customers; use activation resend to submit
|
||||
|
||||
Reference in new issue
Block a user