Skip to content

Phase/9c migration reconciliation operations - #13

Merged
Mujhtech merged 25 commits into
developmentfrom
phase/9c-migration-reconciliation-operations
Jul 31, 2026
Merged

Phase/9c migration reconciliation operations#13
Mujhtech merged 25 commits into
developmentfrom
phase/9c-migration-reconciliation-operations

Conversation

@Mujhtech

Copy link
Copy Markdown
Owner

No description provided.

@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 26cdf88 to 0b52731 Compare July 31, 2026 09:35
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 0b52731 to fc36891 Compare July 31, 2026 09:36
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from fc36891 to b524d2d Compare July 31, 2026 09:36
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from b524d2d to 32c6e66 Compare July 31, 2026 09:37
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 32c6e66 to 42c4ed4 Compare July 31, 2026 09:37
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 42c4ed4 to 6339eb9 Compare July 31, 2026 09:38
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 6339eb9 to 25c9a18 Compare July 31, 2026 09:38
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 25c9a18 to 12cd068 Compare July 31, 2026 09:39
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from 12cd068 to ba84fd1 Compare July 31, 2026 09:39
Base automatically changed from phase/9b-subscription-state-entitlements to development July 31, 2026 09:41
Mujhtech added 11 commits July 31, 2026 10:41
OTLP export was hard-wired to HTTP with no way to authenticate to a
collector, and logs never left stdout.

Add OTEL_EXPORTER_OTLP_PROTOCOL to select http/protobuf or grpc for every
signal, OTEL_EXPORTER_OTLP_HEADERS for collector credentials, and
MOSAIC_OTEL_EXPORTER_TLS_SKIP_VERIFY for a private CA or self-signed
certificate. Header values are secrets: they are never logged and never
echoed in a validation problem. Skip-verify applies only to an https
endpoint, since attaching TLS credentials to a plaintext gRPC endpoint
would silently upgrade a connection the collector is not serving.

Outside development and test, a plaintext or unverified collector
connection is refused at startup unless MOSAIC_OTEL_EXPORTER_ALLOW_INSECURE
acknowledges it, matching the existing database and object-store guards.

Logs now go to stdout and the collector at once, so they are readable
beside the traces they belong to. The bridge sits at the zerolog writer
rather than a hook so exported records keep every structured field.
MOSAIC_OTEL_LOGS_ENABLED=false drops the export half without touching
stdout, traces, or metrics. Telemetry keeps a local-only logger for its
own SDK errors so an export failure cannot feed the failing exporter.

One generic helper applies the endpoint, header, and TLS policy to all
three exporter packages, which otherwise expose the same options under
unrelated types and drift apart.
Add routeHead() in src/lib/routing/route-head.ts so each file route only
supplies its own title (and an optional description) instead of repeating
the product-name suffix and meta shape. Wire it into the root route and
every page route.
…onent

Register application, create Plan/Product/Entitlement/Placement/Paywall,
create Migration Program, add member, and the grant version wizard now open
from a header action in a dialog instead of a form panel below the list. Each
closes on success and resets its form and mutation error on close; the grant
wizard keeps its three steps and moves from a Sheet to the dialog.

Purchase setup no longer carries its own Environment picker or environmentId
search param. It reads the Environment the address names, so the workspace
switcher is the single place that scope changes.

Replaces all 90 native selects with a Base UI Select wrapper. Two things the
primitive imposes are handled once rather than at every call site: the trigger
label resolves from `items`, so callers build one options list and pass it to
both, and `onValueChange` is narrowed to a non-null value because nothing here
uses a null-valued item. The paywall editor inspector derives its items from
the SelectItem children instead, keeping its sixty-odd fields unchanged.

Tests drive the new control through `chooseSelectOption`. An option commits on
pointer release, so a bare click leaves the value untouched, and options only
exist in the DOM while the list is open.
…re v2 contracts

Adds the Billing Migration Operations v1 command and resource schemas, the
Authoritative Entitlement v2 and Billing State Webhook v2 contracts that carry
authority epoch, scope, and transition metadata, their compatibility rules and
cross-platform fixtures, and the Phase 9C contract validation tooling.
Customer Access Token v1, Delivery v3, Commerce Provider, and Billing Ingestion
v1 are unchanged.
Mujhtech added 14 commits July 31, 2026 10:41
Introduces the Phase 9C billingmigration module: program lifecycle with
compare-and-swap state versions, immutable source snapshots/records/manifests,
versioned mapping sets, import batches, shadow projection, divergences, cases,
checkpoints, repairs, stabilization, and completion/retention state, together
with their PostgreSQL repositories and schema migrations 00052-00061.

Source evidence is encrypted with a chunked AES-GCM envelope into a private
bucket and keyring that are validated to be distinct from the public Asset
bucket and the provider credential keyring. Migration credentials are a
separate encrypted subject kind, and the execution plane is off by default
behind MOSAIC_BILLING_MIGRATION_ENABLED.
…on import

Normalizes RevenueCat REST API v2 evidence through the published resource graph
- paginated customers, subscriptions, aliases, and Product bindings - into
append-only source records while keeping exact response pages as raw encrypted
evidence. Unsupported stores quarantine instead of being inferred from
identifier syntax.

Source-pull commands carry snapshot, delta, and final_delta intent and run as
durable, resumable worker jobs; a completed final_delta queues the lease-bound
final-delta evaluation once its provider-validation import settles. Provider
revalidation reuses the accepted Phase 9A ingestion and validation seams, so
source evidence never inserts a Transaction Fact directly.
…uthority

Adds server-owned authority per (project, environment, application, platform)
scope and serves Authoritative Entitlement v2: authority epoch and kind,
explicit scope, transition state, snapshot authority digest, and server-directed
minimum supported SDK/app metadata. An optional known snapshot digest yields
snapshotUnchanged only on an exact match and never selects authority, scope, or
customer.

Unknown authority stays a safe unavailable result rather than inactive access,
and policy_unavailable fabricates no minimum-support policy. Sync observations
are append-only, bounded, and non-sensitive, and serving does not fail when an
observation write fails. Prepared snapshot pointers stay inert until cutover.
Emits authority scope, epoch, and transition events over Billing State Webhook
v2 while preserving HMAC signing, delivery attempts, redelivery idempotency, and
tolerant-consumer policy. V1 destinations keep receiving only v1 events and
never see authority transitions, so they cannot satisfy the authority-aware
readiness gate.

Production programs with active destinations require at least one healthy active
v2 destination with an active signing secret, proven fresh against the
per-Program watermark_max_age_seconds at both promotion and atomic cutover.
…tion

Mounts the Project-scoped Billing Migration Operations v1 surface behind
Environment and Application membership, with command-specific capabilities -
view, manage-source, manage-mappings, run-import, resolve-cases,
propose-cutover, approve-cutover, execute-cutover, execute-rollback,
execute-repair, delete-source - returned by the server as a closed set derived
from the actor and current Program state.

Wires the migration services, worker jobs, and the migration keyring into the
api, worker, keyring, and billing demo commands. Commands carry idempotency
keys, expected state version, and expected digests; a stale digest returns a
stable 409 and leaves authority unchanged.
Adds the Project-scoped migration journey cockpit, guided mapping and mapping
freeze, impact review, and the command, query, and mutation layer against the
frozen Billing Migration Operations v1 API. Every dangerous command gets an
impact preview, an explicit reason, a server-derived capability check, stale
409 handling, and irreversible or rollback consequences; secret inputs clear
after submission and are never read back. Migration semantics stay server-side.
Implements Authoritative Entitlement v2 in the customer entitlement runtime: a
replaying current-authority stream, authority epoch monotonicity ahead of
snapshot version, a cache digest bound to customer, environment, application and
platform scope, and epoch, urgent sync on authority transition ahead of normal
configuration refresh, and authority_unknown for legacy caches and unsupported
contracts.

Access-result APIs are unchanged and unknown or unavailable stays safe. Placement
targeting uses Mosaic-authoritative access only while the current epoch says
Mosaic and never unions it with provider-observed access. Purchase and restore
remain provider-owned, and the Customer Access Token remains memory-only.
Implements Authoritative Entitlement v2 in the Swift SDK: a replaying
current-authority publisher, authority epoch monotonicity ahead of snapshot
version, a cache digest bound to customer, environment, application and platform
scope, and epoch, urgent sync on authority transition, and authority_unknown for
legacy caches and unsupported contracts.

Access-result APIs are unchanged and unknown or unavailable stays safe. Placement
targeting uses Mosaic-authoritative access only while the current epoch says
Mosaic and never unions it with provider-observed access. StoreKit purchase and
restore remain independent, and the Customer Access Token remains memory-only.
Implements Authoritative Entitlement v2 in the Kotlin SDK: a replaying
current-authority flow, authority epoch monotonicity ahead of snapshot version, a
cache digest bound to customer, environment, application and platform scope, and
epoch, urgent sync on authority transition, and authority_unknown for legacy
caches and unsupported contracts.

Access-result APIs are unchanged and unknown or unavailable stays safe. Placement
targeting uses Mosaic-authoritative access only while the current epoch says
Mosaic and never unions it with provider-observed access. Play Billing purchase
and restore remain independent, the Customer Access Token remains memory-only,
and no background scheduler is introduced: foreground recovery plus the existing
refresh mechanisms carry the transition.
Resolving workspace entry from the paginated Organization and Project lists cost
one request per Organization and could not pick a destination without a round
trip per candidate. Bootstrap returns every Organization the actor belongs to
with the actor's role and that Organization's active Projects in a single read,
bounded to 25 Projects per Organization with a truncation flag.
Adds the Phase 9C plan and review notes, ADR 0025 on monotonic scoped billing
authority, the backend notes for the migration foundation, source pull, source
execution, candidate evaluation, webhook v2 transition delivery, and
stabilization/rollback readiness, and the migration keyring rotation procedure.

Regenerates docs/backend/openapi.yaml for the Billing Migration Operations v1
surface, the Authoritative Entitlement v2 sync response, and the workspace
bootstrap read.
OTEL_EXPORTER_OTLP_ENDPOINT is a base endpoint and each signal hangs off it, as
the OpenTelemetry specification defines the variable, so traces, metrics, and
logs now resolve /v1/traces, /v1/metrics, and /v1/logs against it, preserving any
path prefix a gateway mounts OTLP behind. Plaintext is stated to the exporter
explicitly instead of being inferred from the endpoint, so a bare host:port can
no longer silently become TLS.
Moves the organizations feature imports to orgs, replaces the old
/organizations/... links with the current /orgs/.../env/... routes, drops the
monetization workspace's duplicate environment switcher and tab strip now that
the route shell owns them, and clears the transparent scrollbar track.
Pins that the gRPC transport works from the same base endpoint as HTTP: an
in-process collector receives trace, metric, and log exports, so the signal path
the HTTP exporters need stays inert over gRPC, where only the host and the
plaintext flag are read from the endpoint URL.

Also pins endpoint validation for gRPC operators. http:// and https:// URLs are
accepted, including behind a gateway path prefix, and a bare host:port is
rejected: the OpenTelemetry specification defines the variable as a URL, and the
SDK would otherwise fall back to its own default collector instead of the
address that was configured.
@Mujhtech
Mujhtech force-pushed the phase/9c-migration-reconciliation-operations branch from ba84fd1 to 11ffc24 Compare July 31, 2026 09:41
@Mujhtech
Mujhtech marked this pull request as ready for review July 31, 2026 09:41
@Mujhtech
Mujhtech merged commit b4524eb into development Jul 31, 2026
7 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant