Shared Idempotency and Search Foundations
Module-owned business intent replay and authorization-safe multilingual search primitives.
SCRIPE provides reusable idempotency and search primitives. These helpers do not own module business records or policies; each bounded context adopts them through its own application and infrastructure paths.
Module Ownership and Boundaries
The owning module keeps its DbContext, durable receipts, tenant filters, PBAC and field-level security checks, feature and quota rules, and response contract. Shared Core code may normalize or rank caller-provided values, but it must not query another module's persistence or define Party's contact, duplicate, or merge policies.
Backend Idempotency
Use one stable key for one business intent and keep it separate from per-attempt replay-protection nonces. The owning module defines the operation and semantic request fingerprint, persists its durable receipt with the mutation and applicable quota or outbox effects in the same local transaction where that guarantee is implemented, and checks current tenant and authorization before replay. Matching requests can replay the stored result; reusing the key with a changed request should conflict. Outbox delivery remains at least once, so a consequential consumer commits its inbox receipt with its own effect.
Intent key K1 + payload A → first request
Retry K1 + payload A → same-intent replay candidate
Retry K1 + payload B → conflict candidate
New business intent → new key K2Frontend Intent Lifecycle
Create an idempotency key when a user starts a business intent and retain it for retries of that unchanged intent, including a retry after response loss. A changed payload or a new intent needs a new key. Per-attempt replay-protection nonces are separate transport values and must not replace the stable business key. The shared Axios transport retries a mutation only through an explicit opt-in that supplies the endpoint's idempotency key; it keeps that key stable while generating a fresh transport nonce per attempt.
Multilingual Search and Authorization
Use a versioned normalization profile and explicit exact, prefix, token, or fuzzy match classes. The name profiles preserve canonical values; they normalize Unicode and selected Arabic forms, while profiles 2 and 3 preserve Alif Maqsura. Profile 3 removes Arabic harakat and Latin accent marks while preserving combining marks in other scripts. OrganizationCore reads profiles 3, 2, and 1 and dual-writes profiles 3 and 2 during bounded operator backfill. The matcher requires matching profiles, caps input at 256 characters and 16 tokens, requires exact matches for tokens shorter than four runes, and permits at most one edit for longer tokens. Fuzzy similarity is a retrieval aid, never proof of identity or permission to merge. The owning module filters by tenant, PBAC, and field visibility in the query before candidate selection, count, ranking, or paging; it also bounds candidates and pages and defines deterministic sorting. OrganizationCore's branch-name adopter caps candidates at 500 and pages at 100. Phone normalization requires an explicit region; email normalization preserves the local part and converts the domain using IDNA. These helpers do not provide phone or duplicate-contact database search, and normalized values do not establish identity equality.
Adoption and Evidence Boundaries
OrganizationCore is a PostgreSQL-tested adopter for branch-name lookup; selected SQL Server LocalDB facts are also recorded. A focused HTTP fact verifies Arabic/fuzzy results, hierarchy scope before count/results, and permission denial. HRMS is a PostgreSQL-tested adopter for bounded email-domain alias lookup through its registered HTTP path. These results prove only the behaviors exercised by their tests. The duplicate-candidate scorer accepts an already-authorized bounded candidate list and has no production contact adopter. Party remains independently owned: shared helpers and the handoff contract do not mean Party has adopted them or authorize shared persistence access.