§22 S4: release v0.43.0 — invitation surfaces + role-aware empty states (@S4)

Bump VERSION + frontend/package.json to 0.43.0, add the CHANGELOG entry
(minor, non-breaking — additive endpoints + UI, no migration, no change to
existing authz outcomes), and mark Part E slice S4 shipped in the design doc.

Completes @S4 (C2.1–C2.7 invitation + C3.3–C3.5 role-aware empty states).
Next: S5 (in-app create-project + the global directory, C3.1–C3.2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-06-06 00:30:12 -07:00
parent 93cf506059
commit ff54632657
4 changed files with 65 additions and 6 deletions
+55
View File
@@ -23,6 +23,61 @@ skip versions are the composition of each intervening adjacent
release's steps in order — no A-to-B path is pre-computed beyond
that.
## 0.43.0 — 2026-06-06
**Minor (non-breaking) — §22 three-tier refactor, slice S4: *invitation
surfaces + role-aware empty states.* An Owner can now grant scope roles from the
UI, and each tier shows a role-appropriate empty state. Purely additive over S3:
new endpoints and UI, no schema migration, and no change to existing read or
write semantics. Completes acceptance scenarios `@S4` (C2.1C2.7: invitation
reach, bounding, supersession, and the pending-account floor; C3.3C3.5: the
create-first-collection and propose-first empty states).**
See [`docs/design/2026-06-05-three-tier-projects-collections.md`](./docs/design/2026-06-05-three-tier-projects-collections.md)
(Part E slice S4, Part C.2 and C.3). The in-app create-project flow and the
global-directory empty states (C3.1C3.2) remain S5.
Added:
- **Scope-role invitation surface (§22 C.2)** — `POST
/api/projects/<id>/members` grants `{owner, contributor}` to an existing
account (looked up by email) at the project, or at one collection (with
`collection_id`). The grant writes a `memberships` row immediately and emits a
§15 personal-direct notification (`scope_role_granted`) naming the project and
role — a direct grant, not an accept round-trip. `GET` lists the project
subtree's grants (project-Owner view); `DELETE
/api/projects/<id>/members/<user_id>` (optionally `?collection_id=`) revokes.
- **Invitation gates** — `auth.can_invite_at_project` /
`can_invite_at_collection`: managing membership is an Owner capability bounded
by the inviter's reach. A project Owner grants at the project or any collection
within it; a collection Owner grants only at that collection (never the project
or globally); an RFC Contributor manages no membership.
- **Broader-scope-supersedes (§22 C.2.6)** — granting at a broader scope removes
the grantee's narrower rows that the new grant subsumes (same-or-lower role
rank within the subtree); a stronger child grant survives a weaker parent grant
(no negative override).
- **Pending-account floor (§22 C.2.7)** — a grant to a `pending` deployment
account is recorded but confers no write until the account is granted at the
deployment (the §6 admission floor in `effective_scope_role`).
- **Viewer capability flags** — `GET /api/projects/<id>/collections` carries a
`viewer` block (`can_create_collection`, `can_invite`, `role`); `GET
/api/projects/<id>/collections/<cid>` carries `viewer.can_contribute /
can_invite / role`. These drive the role-aware UI without a second round-trip.
- **Role-aware empty states (§22 C.3.3C.3.5)** — a project Owner landing on an
empty project sees a "Create your first collection" CTA (opening the
create-collection modal — surfacing the S2 endpoint, previously UI-less); a
contributor without create rights sees the bare empty directory; a collection
contributor landing on an empty collection sees "Propose the first entry"
(anonymous readers keep the S2 sign-in prompt). The directory also gains an
Owner-only **Members** control opening the invitation modal.
Upgrade steps:
1. No operator action is required. S4 adds endpoints and UI only — there is no
migration and no change to existing authorization outcomes. A deployment that
was managing `memberships` rows directly (the S3 administrative path) keeps
working; the new UI is an additional way to write the same rows.
## 0.42.0 — 2026-06-05
**Minor (breaking — upgrade steps below) — §22 three-tier refactor, slice S3:
+1 -1
View File
@@ -1 +1 @@
0.42.0
0.43.0
@@ -581,13 +581,17 @@ means the deployment runs and either gains a capability or provably loses none
hidden from the public. **Completes:** `@S3` (all of C.1 — role usage,
inheritance, union, no-negative-override).
- **S4 — Invitation surfaces + role-aware empty states.** The invite UI
- **S4 — Invitation surfaces + role-aware empty states.** *(Shipped v0.43.0.)*
The invite UI
(Owner-only) granting Owner/RFC Contributor at a scope or any scope beneath it,
with §15 notifications and the broader-scope-supersedes rule; the
create-first-collection / propose-first empty states keyed to the actor's role.
**Usable end-state:** an Owner invites collaborators at the right scope from
the UI. **Completes:** `@S4` (all of C.2 — invitation; plus the project/
collection empty states C3.3C3.5).
Modelled as a **direct grant** to an existing account looked up by email (the
C.2 scenarios write the membership row immediately and §15-notify an existing
user — no accept round-trip; inviting a not-yet-account email is out of S4
scope, handled by the admin-create-invite path). **Usable end-state:** an Owner
invites collaborators at the right scope from the UI. **Completes:** `@S4` (all
of C.2 — invitation; plus the project/collection empty states C3.3C3.5).
- **S5 — In-app create-project + the global directory.** The global-Owner
**create-project** action (bot provisions a Gitea content repo + commits to
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "rfc-app-frontend",
"private": true,
"version": "0.42.0",
"version": "0.43.0",
"type": "module",
"scripts": {
"dev": "vite",