# v0.87.13 - pg_tide Outbox Boundary

> **Status:** Implemented
> **Scope:** 6 person-weeks
> **User promise:** *"pg_trickle never lends its owner identity to pg_tide."*
> **Blocked by:** [v0.87.12](v0.87.12.md)
> **Program:** [Lifecycle security reimplementation](../plans/pg_trickle_lifecycle_security_reimplementation_plan.md)

## Theme

Finish the lifecycle-security sequence at the extension boundary. pg_trickle
checks stream ownership, then invokes pg_tide as the original caller so pg_tide
enforces its own API and privilege model. pg_trickle updates its private mapping
only after the external operation succeeds.

The integration must fail cleanly when pg_tide is absent, incompatible, or
denies the caller. It may not grant pg_tide access or duplicate pg_tide's
authorization logic.

## Scope allocation

| Work package | Person-weeks |
|---|---:|
| Caller-context pg_tide invocation | 1.25 |
| Private mapping, provenance, and rollback | 1.25 |
| Version compatibility and operational diagnostics | 1.00 |
| Security, rollback, concurrency, and compatibility tests | 2.50 |
| **Total** | **6.00** |

## Items

### LSEC-19: Preserve the external trust boundary

Resolve and authorize the stream under the outer caller. Invoke supported
pg_tide create, alter, and drop APIs in caller context. Pass canonical object
identity, not unresolved caller text. Do not run an external-extension function
inside an extension-owner-only phase.

### LSEC-20: Atomic private mapping

Register or remove pg_trickle's private mapping in a separate definer phase.
Store enough pg_tide object identity and version provenance to reject stale
name reuse. A pg_tide error or private catalog error rolls back the complete
operation.

### LSEC-21: Explicit compatibility contract

Detect pg_tide absence and unsupported installed versions without parsing error
text. Return errors that name the missing extension, supported version range,
or denied pg_tide operation. Keep the supported-version matrix in tests and
release documentation.

## Required tests

- The matrix covers pg_tide absent, supported and authorized, supported but
  denied, unsupported older, unsupported newer, and upgrade-in-progress states.
- Identity probes inside pg_tide observe the original caller, never the
  pg_trickle owner.
- Owner, non-owner, exact-grant, quoted-name, name-collision, stale-OID, and
  ownership-transfer cases cover create, alter, and drop.
- Failure injection before and after each extension call and mapping mutation
  proves atomic rollback and idempotent retry.
- Concurrent create, drop, and retry use deterministic barriers and leave one
  external object and one matching private row, or neither.
- Fresh-install and v0.87.12 upgrade tests verify policy, ACLs, provenance,
  compatibility errors, and no new private grants.

## Exit criteria

- [x] Every pg_tide call runs as the original caller.
- [x] pg_tide remains the sole authority for its own permissions.
- [x] External objects and private mappings commit or roll back together.
- [x] Absence, denial, and version incompatibility return distinct errors.
- [x] Stale names and OIDs cannot redirect an outbox operation.
- [x] Security, rollback, concurrency, compatibility, upgrade, and full
      repository CI gates pass.
