diff --git a/apps/schema/README.md b/apps/schema/README.md index 4fa8300b..3834b40d 100644 --- a/apps/schema/README.md +++ b/apps/schema/README.md @@ -5,6 +5,10 @@ Static JSON Schemas published at `schema.native-sdk.dev`. - `/app/v1.json` is the stable-major schema URL scaffolded into `app.json`. - `/app.json` is the short-lived current-version alias. +Only those schema URLs are served from this deployment. Every other path +redirects (302) to `https://native-sdk.dev`, so the domain stays a single- +purpose home for the manifest rather than hosting arbitrary content. + Create the Vercel project as `native-schema`, set its root directory to `apps/schema`, leave the framework preset as Other with no build command, and attach `schema.native-sdk.dev`. `vercel.json` sets the output directory to diff --git a/apps/schema/vercel.json b/apps/schema/vercel.json index 8b7d8659..8444b7a9 100644 --- a/apps/schema/vercel.json +++ b/apps/schema/vercel.json @@ -4,6 +4,13 @@ "rewrites": [ { "source": "/app.json", "destination": "/app/v1.json" } ], + "redirects": [ + { + "source": "/((?!app(?:\\.json|/v1\\.json)$).*)", + "destination": "https://native-sdk.dev", + "statusCode": 302 + } + ], "headers": [ { "source": "/app/v1.json", diff --git a/docs/scripts/check-app-schema.mjs b/docs/scripts/check-app-schema.mjs index 983a64af..1ac657c2 100644 --- a/docs/scripts/check-app-schema.mjs +++ b/docs/scripts/check-app-schema.mjs @@ -27,7 +27,22 @@ assert.equal(schema.$defs.dmg.properties.icon_size.maximum, 256); assert.deepEqual(fs.readFileSync(legacyPath), publishedBytes, "legacy docs schema differs from canonical v1"); assert.deepEqual(fs.readFileSync(packagePath), publishedBytes, "published and npm-packaged app schemas differ"); assert.equal(deployment.outputDirectory, "public"); +// /app.json aliases the canonical schema; the redirect's negative lookahead +// keeps both schema URLs local while every other path returns an actual 302. assert.deepEqual(deployment.rewrites, [{ source: "/app.json", destination: "/app/v1.json" }]); +assert.deepEqual(deployment.redirects, [ + { + source: "/((?!app(?:\\.json|/v1\\.json)$).*)", + destination: "https://native-sdk.dev", + statusCode: 302, + }, +]); +const redirectPattern = new RegExp(`^${deployment.redirects[0].source}$`); +assert.equal(redirectPattern.test("/app.json"), false); +assert.equal(redirectPattern.test("/app/v1.json"), false); +assert.equal(redirectPattern.test("/"), true); +assert.equal(redirectPattern.test("/docs"), true); +assert.equal(redirectPattern.test("/app/v2.json"), true); assert.ok(deployment.headers.some((entry) => entry.source === "/app/v1.json")); assert.ok(deployment.headers.some((entry) => entry.source === "/app.json"));