# v0.87.10 - Complete Lifecycle Policy

> **Status:** Implemented (local policy, unit, integration, and light-E2E gates pass; full CI remains authoritative)
> **Scope:** 6 person-weeks
> **User promise:** *"Every lifecycle API has one enforced execution and authorization policy."*
> **Blocked by:** [v0.87.9](v0.87.9.md)
> **Program:** [Lifecycle security reimplementation](../plans/pg_trickle_lifecycle_security_reimplementation_plan.md)

## Theme

Apply the proven owner boundary to the remaining lifecycle APIs. Make the policy
machine-readable, reject unclassified exports in CI, and provide an upgrade
preflight that reports missing owner privileges before the hard cutover.

This release does not add a legacy extension-owner execution mode. Keeping that
path would preserve the privilege escalation that this sequence removes.

## Scope allocation

| Work package | Person-weeks |
|---|---:|
| Remaining single-target lifecycle functions | 1.00 |
| Atomic bulk operations and manual refresh exposure | 1.25 |
| API policy, static boundary checks, and preflight diagnostic | 1.50 |
| Security, batch, upgrade, generated-doc, and regression tests | 2.25 |
| **Total** | **6.00** |

## Items

### LSEC-10: Remaining owner lifecycle APIs

Harden refresh-policy, storage-policy, pause, resume, repair, reset-fuse,
statistics-reset, and manual-refresh entry points. Each function checks the
outer caller against the canonical stream owner before private mutation.

Keep arbitrary-SQL dispatchers and pure checked delegates as invokers. Record
the reason for each exception in the API policy.

### LSEC-11: Atomic bulk lifecycle operations

Resolve and authorize every bulk-alter and bulk-drop target before mutation.
Reuse the single-target prepared plans and drop planner. One invalid, missing,
duplicate, or unauthorized target fails the batch without partial changes.

### LSEC-12: Enforced policy and upgrade preflight

Give every exported lifecycle overload an exact policy classification. CI
rejects an unclassified export, an unpinned definer path, caller-controlled SQL
outside the owner helper, unsafe dynamic identifiers, and external-extension
calls in a definer-only phase.

Add a read-only superuser preflight that lists each owner missing source
`SELECT` or schema `USAGE`, including the exact remediation. Upgrade refuses to
change catalog state until the report is clear.

## Required tests

- A generated matrix exercises every lifecycle overload as owner, non-owner,
  superuser, and a role with only the documented exact grants.
- Bulk tests cover mixed ownership, duplicates, missing targets, cycles,
  mid-plan failure injection, and concurrent target changes.
- Static-checker self-tests include one positive and one negative fixture for
  every rule and fail when a new lifecycle export lacks policy.
- Fresh-install and chained-upgrade tests compare function attributes, ACLs,
  catalog state, preflight output, and generated API documentation.
- Manual refresh repeats the v0.87.8 identity, RLS, rollback, and frontier tests
  through the public API.

## Exit criteria

- [x] Every owner-lifecycle overload has one checked policy classification.
- [x] Bulk operations authorize the complete set before the first mutation.
- [x] The public manual-refresh API preserves the v0.87.8 owner boundary.
- [x] Preflight reports every missing grant and changes no state.
- [x] No legacy extension-owner query-execution mode exists.
- [ ] Policy, generated-doc, security, upgrade, and full repository CI gates pass.
