Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Advisory reviewer routing during the registry preview. Branch protection does
# not require code-owner approval until the permanent review policy is enabled.
* @FlutterFlow/prod-eng
/campus.registry.json @FlutterFlow/prod-eng
/artifacts/ @FlutterFlow/prod-eng
Expand Down
12 changes: 7 additions & 5 deletions .github/REPOSITORY_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ owner must configure the GitHub repository after the initial `main` push.
1. Keep `FlutterFlow/campus-extensions` public and set `main` as the default
branch.
2. Ensure the existing `FlutterFlow/prod-eng` team referenced by CODEOWNERS
retains write access. Replace it with a narrower organization-owned reviewer
team later only as one atomic CODEOWNERS + repository-access change.
retains write access. CODEOWNERS is advisory during the registry preview;
replace it with a narrower organization-owned reviewer team later only as
one atomic CODEOWNERS + repository-access change.
3. Protect `main` with:
- pull requests required;
- at least one approving review, **Require review from Code Owners**, and
stale approvals dismissed;
- approval required for the latest reviewable push;
- zero required approvals during the registry preview, with code-owner and
latest-push approval requirements disabled so maintainers can self-merge;
- required check `Canonical catalog, packages, and tests`;
- branches required to be up to date;
- conversation resolution and linear history required;
- enforcement for administrators;
- force pushes and branch deletion disabled.
Re-enable at least one independent code-owner approval after the preview,
once real extension usage has informed the permanent review policy.
4. Create a GitHub App dedicated to generated publication PRs. Grant it only
repository **Contents: read/write** and **Pull requests: read/write**. Store
its App ID and private key as `CAMPUS_PUBLICATION_APP_ID` and
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/prepare-publication-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
extension_id:
description: Reverse-DNS extension ID already reviewed on main
description: Reverse-DNS extension ID already validated and merged on main
required: true
type: string
description:
Expand Down Expand Up @@ -44,7 +44,7 @@ concurrency:

jobs:
validate-source:
name: Validate reviewed source without publication credentials
name: Validate merged source without publication credentials
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
Expand Down Expand Up @@ -78,7 +78,7 @@ jobs:
with:
node-version: "22"

- name: Validate reviewed source and current catalog
- name: Validate merged source and current catalog
run: |
python3 -m unittest discover -s tool/tests -v
node --test "extensions/$EXTENSION_ID"/test/*.test.mjs
Expand All @@ -88,7 +88,7 @@ jobs:
run: python3 tool/native_release_gate.py --extension "$EXTENSION_ID"

prepare:
name: Package reviewed source and open generated PR
name: Package merged source and open generated PR
needs: validate-source
runs-on: macos-15
timeout-minutes: 20
Expand Down Expand Up @@ -183,7 +183,7 @@ jobs:
run: |
body="$(mktemp)"
printf '%s\n' \
'Generated from reviewed source already merged to `main`.' \
'Generated from validated source already merged to `main`.' \
'' \
'- The artifact is canonical and content-addressed.' \
'- The catalog and archived manifest authority projection match.' \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Check out reviewed bytes
- name: Check out registry bytes
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 1
Expand Down
13 changes: 8 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ product quality and the authority an extension asks users to grant.
real user accounts or depend on host credentials.
6. Run the repository tests and validator.

Every source change requires a pull request, at least one approving review from
a code owner, and all required checks. Force-pushes to the default branch and
direct catalog/artifact edits are prohibited by branch protection.
During the registry preview, every source change requires a pull request and
all required checks, but an independent or code-owner approval is optional.
Maintainers may merge their own green pull requests. We expect to require
independent review once real-world usage gives us enough evidence to tune the
policy. Force-pushes to the default branch and direct catalog/artifact edits
remain prohibited by branch protection.

## Review checklist
## Maintainer checklist

Reviewers check:
Before merge, check:

- the package identity and version are stable and intentional;
- code behavior matches the README and visible UI;
Expand Down
172 changes: 42 additions & 130 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,132 +1,44 @@
# Campus Extensions

This repository is the public, review-first registry for extensions distributed
by FlutterFlow Campus. Campus configures this Git repository as its official
source by default. The catalog points at immutable, content-addressed
`.campusext` archives committed to this repository.

The trust model is deliberately close to Raycast's extension store:

- extension source changes arrive through reviewed pull requests;
- required checks validate manifests, packages, and the complete catalog;
- publication happens in trusted CI after source review, through a second,
generated pull request;
- clients fetch a particular Git commit, require fast-forward history, and
verify every artifact's exact length and SHA-256 digest before installation;
- no registry-specific signature is layered on top of Git provenance and
content addressing;
- native helpers use the v2 package format and must additionally be built in
trusted CI and carry FlutterFlow's Developer ID signature and Apple
notarization.

Installing an extension still means choosing to run reviewed third-party code.
A declared resource request is an authority ceiling and an install-review
surface, not a sandbox promise. In particular, a granted raw process or native
helper runs as the current user and may reach anything that process can reach.

## Repository contract

```text
campus.registry.json
schemas/
campus.registry.v1.schema.json
campus.extension.v3.schema.json
extensions/
<reverse-dns-id>/
campus.extension.json
src/
assets/
README.md
CHANGELOG.md
artifacts/sha256/<64-lowercase-hex>.campusext
tool/
.github/workflows/
```

`campus.registry.json` is canonical JSON: UTF-8, sorted object keys, no
insignificant whitespace, no trailing newline, safe integers only, and packages
strictly sorted by extension ID. Its schema identifier is
`campus.registry.v1`; its registry identity is
`flutterflow.campus-extensions`.

Each release records:

- a strictly increasing package-local sequence and unique semantic version;
- active or withdrawn status;
- exact artifact path, byte length, and SHA-256 digest;
- SHA-256 of the manifest bytes inside that artifact;
- Campus/runtime/platform/architecture compatibility;
- the complete review-facing authority summary used to decide whether an
update can be approved automatically.

The JSON schemas document the wire shape. `tool/registry.py validate` is the
normative repository check because ordering, canonical bytes, cross-file
digests, archive structure, references, and authority projections cannot all be
expressed in JSON Schema.

## Contributor loop

Author source under `extensions/<id>/`. Keep compiled JavaScript in `src/`;
Campus never runs a package manager or compiler while installing. README,
CHANGELOG, tests, and build files remain authoring material and are excluded
from the runtime archive.

Run:

```bash
python3 -m unittest discover -s tool/tests -v
python3 tool/registry.py validate --root .
```

Do not hand-edit `campus.registry.json` or add files directly below
`artifacts/sha256/`. After the source PR merges, a maintainer starts the
**Prepare extension publication PR** workflow. Locally, the equivalent command
is:

```bash
python3 tool/registry.py publish \
--root . \
--extension io.flutterflow.campus.example \
--description "One sentence shown in Extension Center" \
--minimum-campus-version 1.0.0 \
--platform macos \
--architecture arm64 \
--architecture x86_64 \
--feature manifest.v3 \
--feature resources.v3
```

The command validates the source, creates canonical `.campusext` bytes, writes
them only at their digest-addressed path, derives the manifest and authority
digests, inserts the next release sequence, rewrites the catalog canonically,
and validates the whole repository. CI then opens a generated publication PR;
the release is not visible to clients until that PR passes review and merges.

The dependency-free checked-in publisher emits the runtime's canonical,
source-only `.campusext` v1 format. Campus also supports `.campusext` v2 for
manifest-declared native helpers, but native release bytes must first be built,
Developer-ID signed, notarized, and stapled in trusted CI; the signed digest
must then be written into the schema-v3 manifest before the canonical Campus v2
packer runs. Until that trusted v2 publication job is wired into this
repository—and the checked-in validator verifies the same v2 bytes—
`tool/native_release_gate.py` refuses a native declaration with that exact
remediation instead of silently emitting an incomplete v1 archive.

## Client behavior

The official Campus client uses Git as transport, not as an execution root. It
fetches the accepted commit into a sanitized bare repository, reads only the
catalog and referenced blobs, verifies fast-forward ancestry against the
persisted high-water commit, verifies artifact bytes, and installs them into an
immutable local content-addressed store. It does not check out hooks, resolve
submodules or Git LFS, or execute repository files.

Campus refreshes the official source at startup, every six hours, and on manual
refresh. Reviewed updates may activate automatically only when the authority
fingerprint is unchanged. Authority changes wait for review. Failed activation
keeps or restores the previous working release.

## Legal status

No open-source license is granted for the contents of this repository. See
[NOTICE](NOTICE).
The official extension registry for FlutterFlow Campus.

Browse and install curated extensions from **Campus → Settings → Extensions**.

## Available extensions

- [Usage Limits](extensions/io.flutterflow.campus.usage-limits/) — view Claude
Code and Codex usage in one Campus dashboard.

## Contributing

Extensions live under `extensions/<reverse-dns-id>/`.

1. Fork this repository and create a branch.
2. Add or update an extension under `extensions/`.
3. Run the repository checks:

```sh
python3 -m unittest discover -s tool/tests -v
python3 tool/registry.py validate --root .
```

4. Open a pull request.

Do not edit `campus.registry.json` or files under `artifacts/` by hand.
Maintainers publish validated extensions through CI.

See [CONTRIBUTING.md](CONTRIBUTING.md) for the package structure and submission
process.

## Trust and security

Extension source and published artifacts are validated before they reach
Campus. Campus also shows an extension's requested access before enabling it.
Extensions can run with user-granted permissions, so install only extensions
you trust.

Please report security issues as described in [SECURITY.md](SECURITY.md).

## License

No open-source license is granted for this repository. See [NOTICE](NOTICE).
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ and withdraw affected releases when necessary.

## Trust boundary

Git history and SHA-256 content addressing establish which reviewed bytes a
Git history and SHA-256 content addressing establish which accepted bytes a
client received. They do not make extension code harmless. Once a user grants a
raw process, native helper, full filesystem resource, unrestricted HTTP
resource, or raw secret, the extension can exercise that authority without a
Expand All @@ -20,7 +20,7 @@ the host cannot honestly enforce an exact filesystem or network-origin boundary
inside arbitrary child code.

Registry tooling must never execute package code during validation or client
installation. Publication may run reviewed build steps only after merge in a
installation. Publication may run maintainer-approved build steps only after merge in a
trusted job, with signing secrets unavailable to pull-request jobs.

## Response options
Expand Down
2 changes: 1 addition & 1 deletion extensions/io.flutterflow.campus.usage-limits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,4 @@ source pull request.

Validation does not grant the process resource, enable the package, install a
Claude status-line adapter, or execute extension code. Publication is a
separate reviewed catalog/artifact change.
separate generated catalog/artifact change.
5 changes: 5 additions & 0 deletions extensions/io.flutterflow.campus.x-draft-card/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## 0.5.0

- Initial official-registry release of the room-shared X Draft Card.
Loading
Loading