Skip to content

feat(config): federated-config store foundation — publish, discovery, signing, per-org RBAC#2147

Merged
rubenvdlinde merged 1 commit into
developmentfrom
feat/federated-config-store
Jul 26, 2026
Merged

feat(config): federated-config store foundation — publish, discovery, signing, per-org RBAC#2147
rubenvdlinde merged 1 commit into
developmentfrom
feat/federated-config-store

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What

Builds the store surface on the sharing engine (#2134/#2135/#2140): publishing, discovery, provenance signing, and per-org access control.

Endpoint Purpose
POST /api/federated-config/publish Publish a signed bundle to GitHub with the credential the user selected (from the federated-config-credential pref) — never one passed by the caller. 400 when none selected.
GET /api/federated-config/discover?topic= Search GitHub by a type's discovery topic (anonymous, or broker when the user has a credential). Backs a browse UI; never installs.
GET /api/federated-config/public-key The instance's Ed25519 signing key, for other orgs to trust.

Signing / verification (BundleSigner, Ed25519 / libsodium)

Publish signs the canonical bundle (recursively key-sorted, provenance excluded) with a per-instance key minted + stored once. Install verifies:

  • a tampered signature is always refused;
  • unsigned / untrusted-key bundles are refused once the org populates federated_config_trusted_keys (empty = not-yet-enforced, the same idiom as the source allowlist).

Per-org RBAC (FederatedConfigAccess)

Publish/install gated by app-config group allowlists (federated_config_publish_groups / federated_config_install_groups); empty = any signed-in user, admins always allowed.

Tests

  • 15 unit — signer round-trip / tamper / key-order-independent canonicalisation / enforcement; RBAC membership + admin-always + empty-list; install signing gate (tampered→refuse, untrusted→refuse, valid+trusted→install).
  • 6 Playwright e2e (api-direct/federated-config-store.spec.ts).
  • Live-verified on 8080: public-key served (44-char base64); discover returned real GitHub repos; signing enforcement 403 then 200 after clearing (with the appconfig-cache restart); RBAC 403 for a non-admin gated user vs 200 admin; publish 400 with no credential selected.

Note: the broker→GitHub PUT in publish() itself needs a real credential+repo to exercise end-to-end and wasn't live-pushed here; the bundling+signing half and all gating are verified. This unblocks the nc-vue store credential selector + discover UI, and hermiq's cutover onto the shared engine.

@SPEC openspec/changes/federated-config-sharing/specs/federated-config-sharing/spec.md

…iscovery, signing, per-org RBAC

Builds out the store surface on top of the sharing engine (#2134/#2135/#2140):

- **Publish endpoint** `POST /api/federated-config/publish` — publishes a signed
  bundle to GitHub using the credential the USER selected (read from the
  `federated-config-credential` preference), never one passed by the caller.
  Refuses (400) when no store credential is selected.
- **Discovery** `GET /api/federated-config/discover?topic=` — searches GitHub by a
  type's discovery topic (anonymous, or through the broker when the user has a
  credential). Backs a browse UI; never installs.
- **Signing / verification** (`BundleSigner`, Ed25519 via libsodium) — publish
  signs the canonical bundle with the instance key (minted + stored once);
  install verifies. A tampered signature is always refused; unsigned/untrusted
  bundles are refused once the org populates a trusted-keys allowlist (empty =
  not-yet-enforced, the source-allowlist idiom). `GET /api/federated-config/
  public-key` exposes the instance key for others to trust.
- **Per-org RBAC** (`FederatedConfigAccess`) — publish/install gated by app-config
  group allowlists (`federated_config_publish_groups` / `_install_groups`); empty
  = any signed-in user, admins always allowed.

15 unit (BundleSigner round-trip/tamper/canonicalisation/enforcement; RBAC
membership; install signing gate) + 6 Playwright e2e. Live-verified on 8080:
public-key served; discover returned real GitHub repos; signing enforcement 403→
cleared 200 (after appconfig-cache restart); RBAC 403 for a non-admin gated user,
200 for admin; publish 400 with no credential selected.

@SPEC openspec/changes/federated-config-sharing/specs/federated-config-sharing/spec.md
@rubenvdlinde
rubenvdlinde merged commit 62d0d75 into development Jul 26, 2026
16 of 17 checks passed
@rubenvdlinde
rubenvdlinde deleted the feat/federated-config-store branch July 26, 2026 11:25
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openregister @ f04249d

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 174/174
npm ✅ 555/555
PHPUnit
Newman
Playwright ⏭️

Quality workflow — 2026-07-26 11:33 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde added a commit that referenced this pull request Jul 26, 2026
…tandard (#2154)

The change captured only the initial design (5 requirements, most tasks open). It
now reflects everything shipped and merged across the fleet:

- 6 new requirements — schema-marker mechanism (REQ-FCS-006), Ed25519 signing +
  verification (007), per-org group RBAC (008), config sets (009), repo-creation +
  topic-tagging + fetch bridge (010), and installable config-set repositories /
  OpenBuild convergence (011). Each with scenarios; `openspec validate --strict`
  passes.
- tasks.md updated to the shipped reality with PR references across openregister
  (#2134/#2135/#2140/#2147/#2148/#2149), nldesign #192, the 8 app markers, hermiq
  #126/#127, openbuild #181, nc-vue #242 — plus the real-GitHub end-to-end
  verification and the two external follow-ups.
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