Skip to content

feat(schemas): versioned schema ids, hosted on friggframework.org - #705

Open
seanspeaks wants to merge 2 commits into
nextfrom
feat/hosted-schemas
Open

seanspeaks wants to merge 2 commits into
nextfrom
feat/hosted-schemas

Conversation

@seanspeaks

@seanspeaks seanspeaks commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Gives every Frigg JSON Schema one identifier pattern and publishes the files at that URL, following the "Hosted schemas" amendment to ADR-051 (on #666, commit 923c975).

  • Pattern: https://friggframework.org/schemas/<name>/v<major>.<minor>.json. The $id is exactly that URL.
  • Ids moved to v1.0: the ten schemas in @friggframework/schemas used two unversioned styles, friggframework.org/schemas/<name>.json for the api-* schemas and schemas.friggframework.org/<name>.schema.json for the other six. Neither resolved. They're now .../schemas/<name>/v1.0.json. They start at 1.0 rather than 0.x because they've shipped in every 2.0 prerelease and app-definition is enforced by frigg validate/build/deploy, so they're supported contracts. v1.0 is frozen when 2.0.1 ships.
  • Aliases: the old ids remain registered with Ajv for one release, in index.js and in the middleware (schema-ids.js). getSchema() now accepts a name, an $id, or a legacy id. No code in the monorepo looked a schema up by URL: lookups are by file name and are unchanged. There are no cross-schema $refs.
  • Website: scripts/sync-hosted-schemas.js (npm run sync:hosted in packages/schemas) copies each schema to website/schemas/<name>/v<x.y>.json, choosing the path from its $id. The copies are committed, not generated during the Netlify build:
    • Netlify's base directory is website/, so the site builds when website/ changes. With committed copies, a schema change is a website change, and there's no build command or ignore rule to maintain.
    • An old version stays in website/schemas/ after its schema moves on, so a published URL keeps resolving. A build-time copy of the current files would drop it.
    • Reviewers see the published bytes in the diff.
  • Headers: website/_headers serves /schemas/* as application/schema+json with Access-Control-Allow-Origin: *.
  • Stack B schemas: the sync script also reads packages/core/integrations/definitions/schema/ when that directory exists, so the ADR-063 schemas (capability-manifest/v0.1, which the API module manifests already reference) get published as soon as they land on next. Until they're synced, the test fails. This PR doesn't change those files.

Validation stays offline

The runtime, frigg validate and the CLI resolve every $id from the installed package. Nothing configures Ajv loadSchema. A test loads the package with http, https and fetch stubbed to throw, then resolves every $id and every alias.

Test plan

  • packages/schemas: npx jest passes, 7 suites / 155 tests (baseline on next: 6 suites / 127 tests)

  • npm run validate (packages/schemas): 10 schemas valid

  • npm run check:hosted: 10 hosted schemas in sync

  • New tests/hosted-schemas.test.js checks four things:

    • every $id matches the pattern and the file name
    • every website copy is byte-identical to its source
    • every file in website/schemas/ sits at the path its $id names
    • _headers covers /schemas/*, and ids and aliases resolve with no network access

    I also checked that it fails when a copy is edited and when the aliases are removed.

  • After merge: curl -I https://friggframework.org/schemas/app-definition/v1.0.json returns 200 with application/schema+json

Notes

  • feat(devtools): frigg validate, and make the app-definition schema match the runtime (ADR-051) #666 rewrites app-definition.schema.json. Whichever PR merges second takes the other's $id line and reruns npm run sync:hosted.
  • Name clash to resolve on the ADR-063 stack: it uses integration-definition/v0.1 for the declarative document, while this package's integration-definition (now v1.0) is the class Definition schema. The amendment gives the declarative document the name ADR-063 already plans: integration-document.

🤖 Generated with Claude Code

https://claude.ai/code/session_013b2UUFaQ5Lk6TFPqzRr1j7


Note

Medium Risk
Changes public schema $id URLs (mitigated by temporary legacy aliases); validation behavior should stay equivalent if callers used file names, but external $schema references must adopt the new URLs.

Overview
Introduces versioned, publicly hosted JSON Schema identifiers (ADR-051): every package schema’s $id is now https://friggframework.org/schemas/<name>/v1.0.json, replacing the previous unversioned friggframework.org and schemas.friggframework.org URLs.

Runtime and tooling gain schema-ids.js with parseSchemaId, legacy-id aliases (one release), and addSchemaWithAliases so Ajv, getSchema(), and validate() accept schema names, new $ids, or old ids without HTTP fetches. The Express middleware registers the same aliases.

Publishing adds npm run sync:hosted / check:hosted to copy schemas into committed website/schemas/ paths derived from $id, plus Netlify website/_headers for application/schema+json and open CORS on /schemas/*. hosted-schemas.test.js enforces id shape, byte-identical website copies, offline resolution, and header coverage.

Reviewed by Cursor Bugbot for commit f070722. Bugbot is set up for automated code reviews on this repo. Configure here.

📦 Published PR as canary version: 2.0.0--canary.705.f070722.0

✨ Test out this PR locally via:

npm install @friggframework/admin-scripts@2.0.0--canary.705.f070722.0
npm install @friggframework/core@2.0.0--canary.705.f070722.0
npm install @friggframework/devtools@2.0.0--canary.705.f070722.0
npm install @friggframework/eslint-config@2.0.0--canary.705.f070722.0
npm install @friggframework/prettier-config@2.0.0--canary.705.f070722.0
npm install @friggframework/schemas@2.0.0--canary.705.f070722.0
npm install @friggframework/serverless-plugin@2.0.0--canary.705.f070722.0
npm install @friggframework/test@2.0.0--canary.705.f070722.0
npm install @friggframework/ui@2.0.0--canary.705.f070722.0
# or 
yarn add @friggframework/admin-scripts@2.0.0--canary.705.f070722.0
yarn add @friggframework/core@2.0.0--canary.705.f070722.0
yarn add @friggframework/devtools@2.0.0--canary.705.f070722.0
yarn add @friggframework/eslint-config@2.0.0--canary.705.f070722.0
yarn add @friggframework/prettier-config@2.0.0--canary.705.f070722.0
yarn add @friggframework/schemas@2.0.0--canary.705.f070722.0
yarn add @friggframework/serverless-plugin@2.0.0--canary.705.f070722.0
yarn add @friggframework/test@2.0.0--canary.705.f070722.0
yarn add @friggframework/ui@2.0.0--canary.705.f070722.0

@seanspeaks seanspeaks added release Create a release when this pr is merged prerelease This change is available in a prerelease. labels Oct 23, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@netlify

netlify Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for friggframework-org ready!

Name Link
🔨 Latest commit f070722
🔍 Latest deploy log https://app.netlify.com/projects/friggframework-org/deploys/6adc9e952a8abd1cd84ddeb8
😎 Deploy Preview https://deploy-preview-705--friggframework-org.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@cursor

cursor Bot commented Oct 24, 2026

Copy link
Copy Markdown

Frigg 2.0.1 review (Group 2) — COMMENT only

Checklist

  • $id pattern https://friggframework.org/schemas/<name>/v<major>.<minor>.json: pass
  • Legacy ids registered as aliases: pass (schema-ids.js + addSchemaWithAliases)
  • Validation never touches the network: pass (offline tests stub http/https/fetch)
  • website/schemas/ byte-identical to sources: pass (verified cmp for all ten)
  • _headers Content-Type + CORS: pass
  • Conflicts with #666 on app-definition.schema.json: fail (blocking merge-order)

Verdict (would): changes needed

Findings

  1. blocking — packages/schemas/schemas/app-definition.schema.json / website/schemas/app-definition/v1.0.json

    • Hosted v1.0 is a copy of current next, not the ADR-051/#666 schema (still has old managementMode defaults, old postgres management enum, no validate-era keys, old $id migration only).
    • Scenario: Merge #705 as-is → friggframework.org publishes an immutable app-definition/v1.0.json that rejects what #666 will require (and what #639 already scaffolds with 'external'). Editors and $schema users lock to the wrong contract; #666 then either rewrites published v1.0 (violates the amendment) or ships a second incompatible source of truth. Rebase onto / merge after #666 (with 'none' + 'external'), re-run sync:hosted, then ship v1.0 once.
  2. nit — amendment on #666 says capability-manifest / ADR-063 schemas stay at v0.1; this PR only hosts the ten package schemas (fine). Document that sync:hosted will start failing once those land until they are added — already noted in the ADR consequences.

Implementation of ids, aliases, offline resolve, and headers looks correct.

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://schemas.friggframework.org/app-definition.schema.json",
"$id": "https://friggframework.org/schemas/app-definition/v1.0.json",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking (merge order with #666): this renames $id to …/app-definition/v1.0.json but the document body is still the pre-#666 schema. ADR-051’s hosted-schemas amendment makes v1.0 immutable once published.

Scenario: Ship this before #666 → public v1.0 rejects postgres.management: 'external' and fieldLevelEncryptionMethod: 'none', then #666 cannot safely overwrite the same URL. Sync hosted copies from the post-#666 schema (with those enums) before freezing v1.0.

seanspeaks and others added 2 commits October 24, 2026 08:03
Every schema in @friggframework/schemas now has the $id
https://friggframework.org/schemas/<name>/v1.0.json (ADR-051, "Hosted
schemas" amendment), replacing the two unversioned styles
(friggframework.org/schemas/<name>.json and
schemas.friggframework.org/<name>.schema.json), neither of which resolved.

- The old ids stay registered as Ajv aliases for one release, in the
  package and in the middleware; getSchema() accepts a name, an $id or a
  legacy id.
- scripts/sync-hosted-schemas.js copies each schema to
  website/schemas/<name>/v<x.y>.json, the path its $id names; the copies
  are committed so old versions keep resolving and a schema change is a
  website change. website/_headers serves them as application/schema+json
  with open CORS.
- tests/hosted-schemas.test.js checks the id pattern, that every website
  copy matches its source and sits at its $id's path, and that every id and
  alias resolves from the package with http, https and fetch stubbed to
  throw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013b2UUFaQ5Lk6TFPqzRr1j7
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prerelease This change is available in a prerelease. release Create a release when this pr is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant