ManifestApi
in package
Plans and applies a §27.6 manifest (CONTRACT.md §27.6, §27.7).
Two operations, with deliberately different risk profiles:
- self::plan() writes nothing. It reads the tenant and reports the difference. Safe against production, safe in CI, safe to run on a schedule.
- self::apply() performs the plan, stopping at the first failure and NOT rolling back (§27.7). What already landed stays landed, and the returned ApplyReport says exactly what that was.
Both build on the ordinary §27 namespace handles — there is no separate manifest endpoint on the server, and this class invents no wire protocol. It is a client-side convergence loop over operations the imperative surface already exposes, which is why everything §27.8 guarantees about that surface (CSRF, cookies, tenant header, TLS, retry, telemetry) holds here too.
Table of Contents
Methods
- __construct() : mixed
- apply() : ApplyReport
- Applies a manifest, stopping at the first failure.
- plan() : ManagementPlan
- Computes what an apply would do. Sends only reads.
Methods
__construct()
public
__construct(ManagementApi $management) : mixed
Parameters
- $management : ManagementApi
-
The management surface to read and write through.
apply()
Applies a manifest, stopping at the first failure.
public
apply(ManagementManifest $manifest) : ApplyReport
Re-plans internally rather than taking a plan as an argument, so what is applied is computed against the tenant's state NOW. A plan handed in from an earlier run describes a tenant that may have moved since, and applying it would either duplicate work or fail on a conflict — either way acting on a world that no longer exists.
Two phases. First, every entity's own Create/Update lands, in the manifest's derived order — this is §27.6 rule 5's ordering, and it is what makes the second phase possible: a role exists before anything tries to grant it a permission. Second, §13 row 17's fix: role permission grants and group role bindings are reconciled — ADDITIVELY, never revoked or unassigned (§27.6 rule 4's "omission is never deletion", extended to edges the same way it already governs entities) — for every role/group the manifest declares grants/roles for, whether or not that role/group's OWN fields needed a Create or Update. A role that already exists, unchanged, with a grant added to the manifest since the last apply still gets that grant on this run.
Parameters
- $manifest : ManagementManifest
Tags
Return values
ApplyReportplan()
Computes what an apply would do. Sends only reads.
public
plan(ManagementManifest $manifest) : ManagementPlan
Parameters
- $manifest : ManagementManifest