Skip to content
Open
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
21 changes: 17 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,30 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Install Chromium
run: npx playwright install chromium
- name: Install browser engines
run: npx playwright install --with-deps chromium firefox webkit

- name: Format check
run: npm run fmt --workspaces --if-present -- --check

- name: Lint
run: npm run lint
run: |
npm run lint
npm run lint:qualification

- name: Build
run: npm run build

- name: Compiled runtime acceptance
# These process-lifecycle checks use Unix SIGTERM semantics.
if: runner.os == 'Linux' || runner.os == 'macOS'
run: npm run test:runtime

- name: Test
run: npm test && npm run typecheck && npm run test:journey && npm run openapi:check && npm run test:browser
run: npm run test:qualification && npm test && npm run typecheck && npm run test:journey && npm run openapi:check && npm run test:browser

- name: Installed provider contracts
run: npm run test:provider-installed && npm run test:provider-types

- name: Signed provider browser journeys
run: npm run test:provider-browser
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Changelog

## Unreleased

### Breaking changes

- Require the coordinated Askr 0.5 platform packages. Generate ordinary locks
against the frozen candidate registry until publication; a published 0.4
installation cannot provide the new provider presets and session contracts.
- Provider authentication uses server-owned sessions and public provider presets.
Browser token SDKs and the retired `@askrjs/auth/browser` and
`@askrjs/auth/auth0` paths are not consumer contracts for these applications.

### Added

- A separately installable Auth0, Microsoft, Google and Apple application with
SSR and SPA modes, server actions, HTTPS, and signed simulated provider tests.
- Independent stage installation, lock replay and compiled API, MCP and SSG
runtime qualification against the frozen package graph.

### Fixed

- Retire private provider-page state and recover through login with `next` when
a live private-query request returns 401 after session expiry. Ignore late
unauthorized responses from requests belonging to a retired identity.

- Declare SPA's own jsdom dependency and keep installed/generated files outside
each stage's lint and format scope.
- Preserve the API/SSR DOMPurify override for standalone installation.
- Mark the SSG root ready after hydration completes so runtime checks can prove
server-node reuse and exactly one interactive acknowledgment.
- Run the provider application's signed Chromium, Firefox and WebKit journeys,
installed public surface and both TypeScript compiler gates in ordinary CI.
- Consume Vite's installed virtual-server declaration without duplicate local
shims and align typed lifecycle test doubles with OpenAPI 3.1.2.
- Resolve the declared TypeScript 6 compiler in both standalone and hoisted
workspace installations.
- Send independent-stage audits to the public advisory database while retaining
the frozen candidate registry for package installation.
- Qualify all 54 signed provider browser cases through an explicit simulated
provider handoff and strict loopback CONNECT transport. Preserve Apple's
cross-site `form_post`, canonical authorization parameters, actual callback
cookies, exact private-request cancellation and bounded cleanup.
- Start Google sign-in with identity scopes, then request Calendar permission
through the first server action's explicit consent flow.
- Verify each candidate archive's served SHA-256 and SRI before independent
application installation, retaining an archive receipt and rejecting redirects.
- Map the provider example's shared environment settings to `askr add auth`
output while preserving matching credential names and callback routes.
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,45 @@ Install and run all repository gates from this directory:
npm install
npm run check
npm run build
npm run test:runtime
npm run test:browser
```

## Supplemental references

- [`api-only/`](api-only/) is the small server reference. Its health and user API patterns are reused directly by `api-ssr`.
- [`ssg/`](ssg/) generates public runbook pages, expands parameterized entries, emits metadata, and hydrates a small interactive control.
- [`mcp-server/`](mcp-server/) runs compiled MCP servers over stdio or HTTP, with an optional stateful session and progress stream.
- [`provider-auth/`](provider-auth/) extends the authenticated journey with one server-owned Auth0, Microsoft, Google or Apple session, explicit SSR/SPA boot, server-only API permissions and local logout.

Every workspace can also be copied, installed, tested, and run from its own directory. Local `file:` dependencies point at sibling platform packages during platform development.
Every workspace can also be copied, installed, tested, and run from its own directory. Dependencies use ordinary registry ranges. API/SSR owns its DOMPurify override so copying the stage preserves the same patched dependency as the root workspace.

## Platform boundary

The examples intentionally exclude developer tools, databases and ORMs,
identity-provider ownership, vendor deployment adapters, WebSockets, and
vendor deployment adapters, WebSockets, and
proprietary telemetry backends. Those remain application or adapter choices,
not hidden framework defaults.

## Consumer qualification

`npm run acceptance` runs the existing workspace contracts, production builds, compiled API and MCP transport checks, built SSG browser hydration and incremental generation, and the SPA/SSR/API-SSR browser journeys. The runtime gate starts fresh processes and records evidence in a printed temporary directory. It requires the Playwright Chromium binary (`npx playwright install chromium`). SSG marks `#app` ready only after `hydrateSPA` completes; its browser check preserves actual server-created nodes and observes one acknowledgment toggle.

See [`scripts/qualification/README.md`](scripts/qualification/README.md) for standalone stage installs and the separate final release-candidate mode. Published 0.4 baseline results do not qualify the unpublished 0.5 graph.

## Provider session extension

The provider example is a separate, independently installable workspace. Its
[README](provider-auth/README.md) explains the single server authority, HTTPS
setup and provider registration. It preserves the earlier deterministic login
example as a small teaching stage rather than replacing it.

`npm run check` and `npm run build` include the new stage. After installing all
three Playwright engines, `npm run test:provider-types` checks its own strict
TypeScript 6 and 7 compilers, and `npm run test:provider-browser` builds the
native fixture and exercises all four signed simulated providers in both SSR
and pure SPA modes on Chromium, Firefox and WebKit. `npm run acceptance` includes
these gates. The fixtures use real HTTPS, signatures, PKCE and server actions;
they do not establish live-provider compatibility. No provider credentials are
needed for the simulated suite. Producer retirement and final 0.5 package graph
qualification remain prerequisites for running this newly prepared extension.
7 changes: 7 additions & 0 deletions api-only/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
dist/
.vite/
.vitest/
coverage/
playwright-report/
test-results/
10 changes: 5 additions & 5 deletions api-only/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
"check": "npm run lint && npm run typecheck && npm test && npm run openapi:check"
},
"dependencies": {
"@askrjs/auth": ">=0.4.0 <0.5.0",
"@askrjs/node": ">=0.4.0 <0.5.0",
"@askrjs/schema": ">=0.4.0 <0.5.0",
"@askrjs/server": ">=0.4.0 <0.5.0"
"@askrjs/auth": ">=0.5.0 <0.6.0",
"@askrjs/node": ">=0.5.0 <0.6.0",
"@askrjs/schema": ">=0.5.0 <0.6.0",
"@askrjs/server": ">=0.5.0 <0.6.0"
},
"devDependencies": {
"@askrjs/cli": ">=0.4.0 <0.5.0",
"@askrjs/cli": ">=0.5.0 <0.6.0",
"tsx": "^4.23.12",
"typescript": "^7.0.2",
"vite-plus": "^0.3.1",
Expand Down
2 changes: 1 addition & 1 deletion api-only/tests/api-only.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it } from "vite-plus/test";
import { createApp } from "../src/app.js";
import { createDependencies } from "../src/boot/dependencies.js";
import api from "../src/api.js";
Expand Down
7 changes: 7 additions & 0 deletions api-ssr/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
dist/
.vite/
.vitest/
coverage/
playwright-report/
test-results/
31 changes: 17 additions & 14 deletions api-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,33 @@
"check": "npm run lint && npm run typecheck && npm test && npm run openapi:check"
},
"dependencies": {
"@askrjs/askr": ">=0.4.0 <0.5.0",
"@askrjs/auth": ">=0.4.0 <0.5.0",
"@askrjs/charts": ">=0.4.0 <0.5.0",
"@askrjs/i18n": ">=0.4.0 <0.5.0",
"@askrjs/lucide": ">=0.4.0 <0.5.0",
"@askrjs/monaco": ">=0.4.0 <0.5.0",
"@askrjs/node": ">=0.4.0 <0.5.0",
"@askrjs/otel": ">=0.4.0 <0.5.0",
"@askrjs/schema": ">=0.4.0 <0.5.0",
"@askrjs/server": ">=0.4.0 <0.5.0",
"@askrjs/themes": ">=0.4.0 <0.5.0",
"@askrjs/ui": ">=0.4.0 <0.5.0",
"@askrjs/askr": ">=0.5.0 <0.6.0",
"@askrjs/auth": ">=0.5.0 <0.6.0",
"@askrjs/charts": ">=0.5.0 <0.6.0",
"@askrjs/i18n": ">=0.5.0 <0.6.0",
"@askrjs/lucide": ">=0.5.0 <0.6.0",
"@askrjs/monaco": ">=0.5.0 <0.6.0",
"@askrjs/node": ">=0.5.0 <0.6.0",
"@askrjs/otel": ">=0.5.0 <0.6.0",
"@askrjs/schema": ">=0.5.0 <0.6.0",
"@askrjs/server": ">=0.5.0 <0.6.0",
"@askrjs/themes": ">=0.5.0 <0.6.0",
"@askrjs/ui": ">=0.5.0 <0.6.0",
"@opentelemetry/api": "^1.9.1",
"monaco-editor": "^0.56.0"
},
"devDependencies": {
"@askrjs/cli": ">=0.4.0 <0.5.0",
"@askrjs/vite": ">=0.4.0 <0.5.0",
"@askrjs/cli": ">=0.5.0 <0.6.0",
"@askrjs/vite": ">=0.5.0 <0.6.0",
"tsx": "^4.23.12",
"typescript": "^7.0.2",
"vite": "npm:@voidzero-dev/vite-plus-core@^0.3.1",
"vite-plus": "^0.3.1",
"vitest": "^4.1.11"
},
"overrides": {
"dompurify": "3.4.16"
},
"engines": {
"node": ">=24.0.0"
},
Expand Down
6 changes: 1 addition & 5 deletions api-ssr/src/vite-server.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
declare module "virtual:askr-server" {
import type { ServerApp } from "@askrjs/server";
export const app: ServerApp;
export default app;
}
/// <reference types="@askrjs/vite/server" />
2 changes: 1 addition & 1 deletion api-ssr/tests/api-ssr.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it } from "vite-plus/test";
import {
createDataRuntime,
createMutation,
Expand Down
2 changes: 1 addition & 1 deletion api-ssr/tests/queries.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
import {
activityQuery,
dashboardQuery,
Expand Down
2 changes: 1 addition & 1 deletion api-ssr/tests/redirect.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it } from "vite-plus/test";
import { safeNextPath } from "../src/features/session/redirect.js";

describe("safeNextPath", () => {
Expand Down
114 changes: 114 additions & 0 deletions docs/0.5.0-candidate-inventory.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"schemaVersion": 1,
"version": "0.5.0",
"packages": {
"@askrjs/askr": {
"version": "0.5.0",
"integrity": "sha512-VaMVh23Qj/pik7j1y57t0JzKpKhYq8zO+0UmVfzleDVNme73pI/C0iNOYtJuaYYaAV5+fsSCUpvX7TPgeCuYSA==",
"tarballSha256": "cbd1fa943c75cdf5781eb4d63f2cc74bae308afc9f13c9f447f58220843d7984",
"sourceCommit": "86da1b1b6bb03afcbc43531c3df0d05fb120ee3b"
},
"@askrjs/auth": {
"version": "0.5.0",
"integrity": "sha512-2quLsDz8mH/6eyKSdcKLJcJQFPcNU2P5H8lS56/IzMzPOt3eihO17e1W5DDnVNMYbNaGVc5FJwWj9Snz0++ygw==",
"tarballSha256": "804da85620e477eb97504e309dc7ac8525b25501fe915e5b81ad68b02bcbbb1e",
"sourceCommit": "e2c14a36628b6a27e62e6aa64d7186fd332ae0b3"
},
"@askrjs/schema": {
"version": "0.5.0",
"integrity": "sha512-JMciK1KmJJ7Jy/GY+ph3ibFf/75qFA1HXMuC0tI/QMxnqpVTbIY694AXk9KDODrY1qm8WaF9ktpjKlY7ciENgA==",
"tarballSha256": "8f0ec7ff67a22d8c670cff3fac7d77543a9d2bd7f882ec67694b7f7a01c97202",
"sourceCommit": "1db2180372325b8187c0d36c12142425972d0f4e"
},
"@askrjs/server": {
"version": "0.5.0",
"integrity": "sha512-piD546hjlQElDs+7fNbTCBE85qdnpZRnLmcOUAoalI1l7h6+Elpp0/+nkfVVim2BMnNs8CTqW01Cwpxv/hv9pA==",
"tarballSha256": "a35847ca7dadeae61fa77c48ab4bff8025d34b02f213617f1c8d18af879f50fd",
"sourceCommit": "583b438a86c16961c86c555836fe16bd8d736a52"
},
"@askrjs/logos": {
"version": "0.5.0",
"integrity": "sha512-Ko3Cf12+qwfoFx1QgDoEANPtFEILyGfSsA1/mwKD8AjTXH3n58cH0bXBv4s6FvfFH46FSIc9xzOr0eTC2YuLkw==",
"tarballSha256": "8d9d770c03e9abcbe8582aadcb6763e9084ffaab9ed5c88e74811794e21161e6",
"sourceCommit": "fbd1b359d7dfb3228fb8c8ee232e1d9bae12d8af"
},
"@askrjs/lucide": {
"version": "0.5.0",
"integrity": "sha512-naFre5an65bHCVYL9lSpdk/InU2PMbfigiY+b4oafNBQpcJWfEFKtZ0EayaVLlGoxDxlg2t4O23DParn8eKQgQ==",
"tarballSha256": "12507f68d30a8e066f242557c411ae7fc633f5b6d12b1488d0991934c2e6b8b0",
"sourceCommit": "af6e8b598c46e7c9ed46dcc0c2621e889650a576"
},
"@askrjs/fetch": {
"version": "0.5.0",
"integrity": "sha512-/eAjeP7x3xPfKaIaa0elg5mjNxx5ZJ51YZR1W5X2BhhVfiIXSxXRMBBa+6QIY9oNbsquzzP3BbJc6TIMlDyFgA==",
"tarballSha256": "a7b659e6d69421e93c42621bf5204e6e051fc264afdeb7ee3cd09f30f08ba3d5",
"sourceCommit": "2ead2cb26c7a4e9879ef20a82aff6c9bdf6e4e23"
},
"@askrjs/testing": {
"version": "0.5.0",
"integrity": "sha512-GR3kKzfmcExylK+jWfIc8fAHK6kqtUDfzP60uNM86HSk0Pc+FFZ+a/ZUULhmqIdv/cZdI29XUejEUQSMY8Ojqg==",
"tarballSha256": "0a6d419b604e143886f32a06ebcaf520a31a7bba96f0b7422393792c8970bf52",
"sourceCommit": "ac32742f7ae23d0f2c76d3f32056cf16e0b1d633"
},
"@askrjs/i18n": {
"version": "0.5.0",
"integrity": "sha512-DN6zf0Ok1zBLFGgm3EY35bITsOpA35qpGWvY7HNLAqw/qLjBn2ijvKEBalhc9+Fvmw72hwjgL/d2df+hWlJYKQ==",
"tarballSha256": "69905691f80f2e5027c64d2eb43d49141bcae29405715740b830fe2c5bccf686",
"sourceCommit": "f8a0f6a9b403bddf1560a5a79a1bcabc334351b7"
},
"@askrjs/orm": {
"version": "0.5.0",
"integrity": "sha512-4T1UfgCdXZN7EjVVUYmcu2wIyQ+rYpipDKJTsOx5yzxKdPcuDAjtAN8uWdgJpsukxHnb0C2aZl0dk+q6Fmu0/Q==",
"tarballSha256": "4790caf6e8dbcfa53e6959b4bb56a3f7810b2502a9f492eae16fcdbf458083fb",
"sourceCommit": "817e1e970a9921df53c8eb756fe1ad4e228a8f6b"
},
"@askrjs/otel": {
"version": "0.5.0",
"integrity": "sha512-sGKn5ny+SlClKG5GnC9fsyE00hAui4SeCm30f4kOHnVHW9CXvJdfggFAK7tG+FZlORtuJnHGjjPf+/59dihMtg==",
"tarballSha256": "f65530a47d83a3462e66dbc7f28eee7b833c62891e7941ab72092630a7927d5f",
"sourceCommit": "8097652fd804e5eb522a8afc8773ec7c1ff31b96"
},
"@askrjs/node": {
"version": "0.5.0",
"integrity": "sha512-HnsI+53V/JPWiEuPk954VTLhHHf+jK0in8Mvq2FKu+fBsaUhJENRiray8BC9LMex5Lvt+czX1XvAF/f4RdBpag==",
"tarballSha256": "d7a00f0a7037062a58126a0fb64b68fba78278b975039b3c23f915c82a0306bf",
"sourceCommit": "335a7c4d85c25a34e0d8a38198eeed01fb7bce52"
},
"@askrjs/vite": {
"version": "0.5.0",
"integrity": "sha512-7V7rS+oF8so2O0Kjr3CQUKtYUJIogP5taogHJTu9kqFrjfuBNpI9aMZkQcS1FwsQnJ9hHOVK1OE0JyDmZ6A92g==",
"tarballSha256": "5cba162e1b4895e98d8c18ecc815dbe59280fec919b665b9faf45667c2773008",
"sourceCommit": "408403aa5feeeea416c00bdc62d58ca343d5d5a9"
},
"@askrjs/ui": {
"version": "0.5.0",
"integrity": "sha512-Q3yvvcah8rp9iWEq7H0uQHU4to4uLx9lT5B8GpXz43qh2i9UVtxjrpJ5rdPWfNiIPCYEkqjDnhpT3JOlMnMOsg==",
"tarballSha256": "df948ddcee3d79a84fa0d6b70bbe884828ceb85849f679251ac3255330b04284",
"sourceCommit": "34ef542427c15dd388ae459181b0565cb27bd997"
},
"@askrjs/monaco": {
"version": "0.5.0",
"integrity": "sha512-oKAtmvvS5ZdB+V4B/Qt1v0781ftS1ZLPU2ErQNZdaVFSox7lXFax1iZYnA2yvuXlATPtax43fLaLwt0WmPiBBQ==",
"tarballSha256": "0749cbe4e5f46cbc4bf2f24349c2ac405166a9b89c456132905e3a3192685a76",
"sourceCommit": "b66806c6b49cd4a19f8ea7f47931f7f213a74845"
},
"@askrjs/charts": {
"version": "0.5.0",
"integrity": "sha512-/pwEk71WlxSGG8FZ71D71kLNDMPqA13eB5i8jxFMuzaY0o1D15nZybziJD5v1S9vlervOryH0AulCmI64Ulfwg==",
"tarballSha256": "1631cfd242f59cd831d4e086e771a394e01a7f49178072827f8a663a4ab5593a",
"sourceCommit": "7992395004b5e725a3870f4b57836a2bfb4630ef"
},
"@askrjs/themes": {
"version": "0.5.0",
"integrity": "sha512-qqR1q8cdl0w8ayXRh45WvEmCgk3WPAcOCeNcOGPm9ymCY7iO5aNjrwxz/hJ9fdrAB1vAGb3FQF5K/uddciZphw==",
"tarballSha256": "b154553c86b1242f251c6185dea3c55b8885eee796c772387258970b2191a8a8",
"sourceCommit": "c71d6686445630cc7b539a9f9ce3140c9c12535e"
},
"@askrjs/cli": {
"version": "0.5.0",
"integrity": "sha512-gn+I+ejpvQ3qI0QbQW4EEEzOawXEBL5+ww7vCx6PDLt0bGBfkufiZ2e5ZYj1+vr60KV0EcvHaRyDKtUB8JFNkg==",
"tarballSha256": "cd0b24b4c91b02067d15bf7e7666947254c5000109dcaf283fc39945b6a3b55d",
"sourceCommit": "9d363290883a183291e53a2cfe60339c391e658f"
}
}
}
Loading
Loading