diff --git a/CHANGELOG.md b/CHANGELOG.md index 104c2cdd..a2d20d77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### 0.55.66 reviewed-master integration (2026-10-30) + +- Normally integrate reviewed master `cffc64c8` after #259, #260 and #261 + merged. Preserve original Hono head `7379a97e` and both documentation + histories. No further dependency version or runtime behavior is added. +- Keep the actual-parent-qualified Hono 2.1.3 override and all incoming + inventory, qs, fast-uri and web dependency corrections. Both roots retain + the reserved 0.55.66 version. New-head graph, restore, protected gates, + clean-CI bytes, independent review and hosted results remain required. +- Parent #261 passed 28/28 gates with API 6,248/215 suites, HTTP 2,514/118 + plus 42 skips and web 1,661/125 files; these are parent provenance, not + assumed new-head results. Performance #251 and every final-artifact hold + remain separate. No benchmark or deployment was started. +- Self-improvement applied: explicit parent/source/complete-graph preservation. + Design accepted: ordinary integration, no new responsibility or abstraction. + +### 0.55.66 preparation - Hono adapter qualified with its real Prisma parent + +- Separate draft rollback unit on exact unmerged #261 head + `f4fcfe3ccac83de6548ed9991ed44048ee8d660a`; 0.55.65 remains reserved + for untouched performance draft #251. +- Select `@hono/node-server` 2.1.3 for GHSA-rmxm-3fg6-px4f after real + Prisma 7.8.0 / dev 0.24.3 old/new startup, HTTP requests, synthetic primary + and shadow database writes, dump, public error and close/cleanup checks. + The declared exact 1.19.11 parent range remains an explicit exception. +- Actual HTTP exploit RED exposes the synthetic protected file at 1.19.15; + 2.1.3 returns 404. Six permanent focused checks have pre-manifest RED: + four failed / two passed, including the exploit and complete inventory. + Final focused GREEN is 6/6 in one suite, targeted lint passes, and full + unfiltered installed npm inventory exits 0 with empty stderr. +- Exact-source CI lock run 40948177653 and authenticated artifact 12929363808 + change only the API adapter outside root records; both clean restores + preserve their source lock bytes. Final clean-installed actual-parent + isolation check passes all 12 claims and removes its owned container. +- Bootstrap protected Fast passes 25/25, with 6,248 API unit and 2,514 + HTTP E2E tests (42 existing skipped). Final Validate/hosted counts are + recorded separately in the bounded handoff after execution, not assumed. +- Both adapters retain a process after successful public close and listener + release. Explicit owned-container stop is recorded, never represented as + natural process exit or concealed by changing Jest worker/exit settings. +- [Qualification, precise limits and execution RCA](docs/HONO_PRISMA_PARENT_QUALIFICATION.md). + No new user interface or SCIM response behavior, merge, deployment, review + approval, performance clearance or release completion is claimed. + ### 0.55.64 reviewed-master integration (2026-10-29) - Normally integrate reviewed master `287ea671` after #259 and #260 merged. diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 9105c409..d07fc7a5 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,6 +1,6 @@ # SCIMServer Deployment Options -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` > Updated: 2026-10-16 - Scope: production + local deployment paths diff --git a/README.md b/README.md index 49190d0a..a5c0ab11 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SCIMServer -> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.66` > Production-ready, multi-tenant SCIM 2.0 server for Microsoft Entra ID provisioning and any RFC 7643/7644-compliant identity client. @@ -9,10 +9,14 @@ cover 0.55.58 correction preparation, merged 0.55.57 source, the deployed 0.55.5 cumulative changes since 0.55.20, migration/rollback steps and known limits. See [CHANGELOG.md](CHANGELOG.md) for detailed engineering history. -**Pending API advisory integration:** [Consumer compatibility and remaining Hono blocker](docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md) -describes proposed 0.55.64 integrating reviewed master after #259 and #260 -merged. Five assessed advisory records are targeted; this proposal is not -a deployed release or full advisory-clearance claim. +**Current Hono source integration:** [Actual Prisma parent qualification](docs/HONO_PRISMA_PARENT_QUALIFICATION.md) +records proposed 0.55.66 integrating reviewed master after #259, #260 and +#261 merged. It preserves the bounded adapter compatibility proof and all +dependency fixes. New-head validation and review remain required; no deployed +release or full advisory/performance admission is claimed. + +**Merged API advisory source:** [Consumer compatibility and historical Hono boundary](docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md) +records the 0.55.64 qs and fast-uri correction merged at `cffc64c8`. **Merged source-only inventory correction:** [API override-context validity](docs/API_OVERRIDE_CONTEXT_VALIDITY.md) describes merged 0.55.63 source and the complete-tree npm regression. It @@ -25,7 +29,7 @@ For actual supported shapes and integration limits, see Keep strict validation enabled for Entra; diagnose the request and effective schema before applying a targeted compatibility setting. -[![Version](https://img.shields.io/badge/version-0.55.64-blue)]() +[![Version](https://img.shields.io/badge/version-0.55.66-blue)]() [![Node.js](https://img.shields.io/badge/Node.js-24-green)]() [![NestJS](https://img.shields.io/badge/NestJS-11.1-red)]() [![PostgreSQL](https://img.shields.io/badge/PostgreSQL-17-blue)]() diff --git a/Session_starter.md b/Session_starter.md index e14dba7d..0badeae1 100644 --- a/Session_starter.md +++ b/Session_starter.md @@ -1,8 +1,52 @@ ## SCIMServer - Condensed Session Memory -**Last verified:** 2026-10-29 +**Last verified:** 2026-10-30 + +### Current Hono reviewed-master integration (2026-10-30) + +PR #261 merged normally at `cffc64c8a188a721fabb85c37a80243d5e65a74f`, +after 28/28 protected Validate gates, seven exact-head checks and separate +technical review. Its counts were API 6,248/215 suites, HTTP 2,514/118 suites +plus 42 existing skips, and web 1,661/125 files. #259 and #260 are merged. + +The preserved 0.55.66 Hono candidate now normally integrates that master. +Five documentation conflicts retain both preparation histories below. +Original Hono head `7379a97e` and its actual-parent qualification remain +preserved. Source/graph preservation and the owned API-only clean restore +pass with both lock byte hashes unchanged; both complete installed inventories +exit 0 and isolated Prisma generation passes. Protected Validate, clean-CI +lock confirmation, separate review and hosted checks remain required. +Performance #251 remains unmerged with a verified same-image control failure; +no repeated campaign, threshold waiver or deployment follows from this merge. +If 0.55.66 merges first, the held 0.55.65 candidate must not downgrade it. -### Current advisory integration (2026-10-29) +| Date | Summary | +|---|---| +| 2026-10-30 | Normally integrate reviewed advisory master into independent Hono #262 at its reserved 0.55.66 boundary; retain both histories and all release holds. | + +### Historical separate Hono real-parent qualification (2026-10-29) + +Proposed 0.55.66 branches from exact unmerged #261 +`f4fcfe3ccac83de6548ed9991ed44048ee8d660a`, not performance #251. +[Real-parent evidence and RCA](docs/HONO_PRISMA_PARENT_QUALIFICATION.md) +records actual Prisma/dev initialization, requests, synthetic database +writes, close/port/data cleanup with old and candidate adapters. Exploit +RED/GREEN is 200 protected-file exposure versus patched 404. Both versions +retain a post-close process; only exact owned containers were stopped. +Six permanent regressions observed pre-manifest RED (four fail/two pass). +Authenticated CI lock run 40948177653 was imported with an adapter-only API +delta and no non-root web delta. Both clean restores preserve lock bytes. +Installed focused GREEN is 6/6; full npm inventory exits 0 with empty stderr. +Final installed parent passes all 12 claims; native invocation refuses before +loading the parent. Bootstrap Fast passes 25/25; final Validate/exact-tip CI +receipts follow separately in the ignored handoff. Draft review and all +release/performance/visual/prod holds remain. + +| Date | Summary | +|---|---| +| 2026-10-29 | Executed isolated actual Prisma parent old/new qualification and exploit RED/GREEN; prepared separate 0.55.66 adapter correction without changing existing drafts. | + +### Historical advisory integration (2026-10-29) PR #260 merged normally at `287ea671abf1619d7b172c495310769078bd685b` after 28/28 protected Validate gates, seven successful exact-head checks and diff --git a/api/package-lock.json b/api/package-lock.json index 8efa1d0f..921bb0d7 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -1,12 +1,12 @@ { "name": "scimserver-api", - "version": "0.55.64", + "version": "0.55.66", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scimserver-api", - "version": "0.55.64", + "version": "0.55.66", "license": "MIT", "dependencies": { "@nestjs/common": "^11.1.27", @@ -765,13 +765,13 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.15", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.15.tgz", - "integrity": "sha512-Za2ai6TLdKjUvnur+eenO6nuYYipVAEhyCAdaV8IRvmU9kK8crOZUSYvIXn72E4f8fJqyAbpcJuTsYYmZp9Deg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.3.tgz", + "integrity": "sha512-TA//nWMqPhbfdfneACk6t5a9eqbS9lABEPyKn0/xZTah3H3U2XaVg85rJFl0/Fyit0I552YDHgXGVSf3GwqbUw==", "devOptional": true, "license": "MIT", "engines": { - "node": ">=18.14.1" + "node": ">=20" }, "peerDependencies": { "hono": "^4" diff --git a/api/package.json b/api/package.json index 2ec131ea..f3a20680 100644 --- a/api/package.json +++ b/api/package.json @@ -1,6 +1,6 @@ { "name": "scimserver-api", - "version": "0.55.64", + "version": "0.55.66", "description": "SCIMServer backend service providing SCIM 2.0 endpoints and logging for troubleshooting.", "license": "MIT", "main": "dist/main.js", @@ -81,7 +81,7 @@ }, "// overrides": "OPS-3 / Trivy gate: pin transitive deps to patched versions for known advisories. Reviewed 2026-09-30. Hono: issue #144. Multer: GHSA-wc9g-mqfw-jrwm, GHSA-qfvm-cv95-jqjf, GHSA-qvfw-j98x-7q72, GHSA-535w-7cp7-47q4. fast-uri: GHSA-5jgf-p345-68v8, GHSA-f65p-4m7j-42xc, GHSA-fph4-wmhf-6fwf, GHSA-jqff-g426-hqxp, CVE-2026-84292, CVE-2026-84394. deepmerge-ts: GHSA-ggr8-5vv4-36mx. mysql2: GHSA-3f6p-5ww8-9rcr, GHSA-rgwj-5xj2-c3m3.", "overrides": { - "@hono/node-server": "1.19.15", + "@hono/node-server": "2.1.3", "defu": "6.1.5", "effect": "3.20.0", "fast-uri": "4.2.3", diff --git a/api/src/scripts/check-hono-parent-qualification.spec.ts b/api/src/scripts/check-hono-parent-qualification.spec.ts new file mode 100644 index 00000000..eaa352d8 --- /dev/null +++ b/api/src/scripts/check-hono-parent-qualification.spec.ts @@ -0,0 +1,121 @@ +import { spawnSync } from 'node:child_process'; +import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { satisfiesGhsaRange } from './check-dependency-pins'; + +type Package = { + name?: string; + version: string; + resolved?: string; + integrity?: string; + dependencies?: Record; +}; +const apiRoot = resolve(__dirname, '../..'); +const readPackage = (path: string): Package => JSON.parse(readFileSync(path, 'utf8')) as Package; +const installedPackage = (name: string, owner = apiRoot): Package => + readPackage(resolve(dirname(require.resolve(name, { paths: [owner] })), '..', 'package.json')); +const lock = JSON.parse(readFileSync(resolve(apiRoot, 'package-lock.json'), 'utf8')) as { + packages: Record; +}; +const manifest = JSON.parse(readFileSync(resolve(apiRoot, 'package.json'), 'utf8')) as { + overrides: Record; +}; +const range = '>= 1.19.10, < 2.1.3'; + +describe('Hono adapter qualification for its actual Prisma parent', () => { + it('distinguishes the affected baseline from the first fixed release', () => { + expect(satisfiesGhsaRange('1.19.15', range)).toBe(true); + expect(satisfiesGhsaRange('2.1.3', range)).toBe(false); + }); + + it('pins every locked occurrence to the qualified public package', () => { + expect(manifest.overrides['@hono/node-server']).toBe('2.1.3'); + const occurrences = Object.entries(lock.packages).filter(([path]) => + path.endsWith('node_modules/@hono/node-server'), + ); + expect(occurrences.map(([path]) => path)).toEqual(['node_modules/@hono/node-server']); + for (const [, entry] of occurrences) { + expect(entry.version).toBe('2.1.3'); + expect(satisfiesGhsaRange(entry.version, range)).toBe(false); + expect(entry.resolved).toBe('https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.3.tgz'); + expect(entry.integrity).toMatch(/^sha512-[A-Za-z0-9+/]+=*$/); + } + }); + + it('keeps the actual Prisma owner and its upstream adapter constraint explicit', () => { + const prismaPath = dirname(require.resolve('prisma/package.json')); + const prisma = readPackage(resolve(prismaPath, 'package.json')); + const devEntry = require.resolve('@prisma/dev', { paths: [prismaPath] }); + const dev = installedPackage('@prisma/dev', prismaPath); + expect(prisma.version).toBe('7.8.0'); + expect(prisma.dependencies?.['@prisma/dev']).toBe('0.24.3'); + expect(dev.name).toBe('@prisma/dev'); + expect(dev.version).toBe('0.24.3'); + expect(dev.dependencies?.['@hono/node-server']).toBe('1.19.11'); + expect(installedPackage('@hono/node-server', dirname(devEntry)).version).toBe('2.1.3'); + expect(lock.packages['node_modules/prisma'].version).toBe(prisma.version); + expect(lock.packages['node_modules/@prisma/dev'].version).toBe(dev.version); + }); + + it('retains the parent-facing adapter exports without opening a listener', () => { + const adapter = require('@hono/node-server') as { + serve: unknown; + getRequestListener: unknown; + createAdaptorServer: (options: { fetch: () => Response; overrideGlobalObjects: boolean }) => { + listening: boolean; + }; + }; + const request = globalThis.Request; + const response = globalThis.Response; + expect(typeof adapter.serve).toBe('function'); + expect(typeof adapter.getRequestListener).toBe('function'); + const server = adapter.createAdaptorServer({ + fetch: () => new Response('synthetic'), + overrideGlobalObjects: false, + }); + expect(server.listening).toBe(false); + expect(globalThis.Request).toBe(request); + expect(globalThis.Response).toBe(response); + }); + + it('rejects the real double-decode exploit while retaining normal routing', async () => { + const { Hono } = require('hono') as typeof import('hono'); + const { serveStatic } = require('@hono/node-server/serve-static') as + typeof import('@hono/node-server/serve-static'); + const root = resolve(apiRoot, '../test-results', `hono-static-regression-${process.pid}`); + mkdirSync(resolve(root, 'static/admin'), { recursive: true }); + writeFileSync(resolve(root, 'static/admin/secret.txt'), 'synthetic-protected'); + writeFileSync(resolve(root, 'static/public.txt'), 'synthetic-public'); + try { + const app = new Hono(); + app.use('/static/admin/*', c => c.text('Unauthorized', 401)); + app.use('/static/*', serveStatic({ root })); + const publicFile = await app.request('/static/public.txt'); + expect(publicFile.status).toBe(200); + expect(await publicFile.text()).toBe('synthetic-public'); + for (const path of ['/static/admin/secret.txt', '/static/%61dmin/secret.txt']) { + const protectedFile = await app.request(path); + expect(protectedFile.status).toBe(401); + expect(await protectedFile.text()).toBe('Unauthorized'); + } + const exploit = await app.request('/static/%%36%31dmin/secret.txt'); + expect(exploit.status).toBe(404); + expect(await exploit.text()).not.toBe('synthetic-protected'); + } finally { + rmSync(root, { recursive: true, force: true }); + } + }); + + it('requires the complete installed npm inventory to be valid', () => { + const npm = process.env.npm_execpath; + expect(npm).toBeDefined(); + const inventory = spawnSync(process.execPath, [npm!, 'ls', '--all', '--json'], { + cwd: apiRoot, encoding: 'utf8', maxBuffer: 32 * 1024 * 1024, + }); + expect(inventory.error).toBeUndefined(); + expect({ status: inventory.status, error: inventory.stderr.slice(0, 1000) }) + .toEqual({ status: 0, error: '' }); + const tree = JSON.parse(inventory.stdout) as { problems?: string[] }; + expect(tree.problems ?? []).toEqual([]); + }); +}); diff --git a/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md b/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md index 277c0044..8e3c26f2 100644 --- a/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md +++ b/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md @@ -4,6 +4,28 @@ ## Executive summary +**Current source boundary (2026-10-30):** the 0.55.64 advisory correction +merged normally as `cffc64c8`. Separate Hono #262 now integrates that reviewed +master at proposed 0.55.66, preserving its actual-parent qualification and +both historical accounts below. New-head verification, review and CI remain +required. No deployment, full advisory clearance or performance admission. +The earlier Hono blocker below describes the 0.55.64 rollback unit, not an +assertion that this separate Hono proposal lacks actual-parent evidence. + +### Historical independent advisory preparation + +**Follow-up, separate rollback unit:** [actual Prisma parent qualification](HONO_PRISMA_PARENT_QUALIFICATION.md) +records the proposed 0.55.66 adapter correction stacked on this draft. +The 0.55.64 blocker below is preserved as the earlier evidence boundary, +not rewritten as if this draft had already qualified the adapter. + +Proposed product 0.55.64 is stacked on draft PR #260 at +`6eb1b59cb1a8ea324bb1a32b17355fabc605279d`. It changes only qs 6.16.0 to +6.16.1 and fast-uri 4.1.5 to 4.2.3. Neither this patch nor its parent is +merged. PR #259 and #251 remain separate. No deployed version changes. + +### Historical reviewed-master advisory integration + Proposed product 0.55.64 now normally integrates reviewed master `287ea671abf1619d7b172c495310769078bd685b`, after #259 and #260 merged. It preserves original advisory head `f4fcfe3c` and every constituent commit. diff --git a/docs/AUTHENTICATION_GUIDE.md b/docs/AUTHENTICATION_GUIDE.md index aab5bc39..a9f9822e 100644 --- a/docs/AUTHENTICATION_GUIDE.md +++ b/docs/AUTHENTICATION_GUIDE.md @@ -1,6 +1,6 @@ # Authentication Guide -> **Status:** Living reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` +> **Status:** Living reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.66` > > **The captured protocol examples below were measured against a running server.** Request and response bodies are verbatim wire captures. Status codes and `reason_code` values are what the server actually returned. The reason-code table in [Section 8](#8-troubleshooting) is generated from [auth-reason-catalog.ts](../api/src/oauth/auth-reason-catalog.ts), so it cannot drift from the implementation. > diff --git a/docs/AZURE_DEPLOYMENT_AND_USAGE_GUIDE.md b/docs/AZURE_DEPLOYMENT_AND_USAGE_GUIDE.md index c854c113..7ce83876 100644 --- a/docs/AZURE_DEPLOYMENT_AND_USAGE_GUIDE.md +++ b/docs/AZURE_DEPLOYMENT_AND_USAGE_GUIDE.md @@ -1,8 +1,8 @@ # Azure Deployment & Usage Guide -> **Status:** User-facing reference - **Last verified:** 2026-08-12 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-08-12 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** June 3, 2026 +> **Version:** 0.55.66 - **Updated:** June 3, 2026 > **Source of truth:** [deploy.ps1](../deploy.ps1), [scripts/deploy-azure.ps1](../scripts/deploy-azure.ps1), [infra/](../infra/) --- diff --git a/docs/COMPLETE_API_REFERENCE.md b/docs/COMPLETE_API_REFERENCE.md index 1b3e5f13..d2c8cb56 100644 --- a/docs/COMPLETE_API_REFERENCE.md +++ b/docs/COMPLETE_API_REFERENCE.md @@ -1,8 +1,8 @@ # Complete API Reference -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** 2026-10-16 +> **Version:** 0.55.66 - **Updated:** 2026-10-16 > **Current release:** [Release notes, upgrade steps and validation limits](RELEASE_NOTES.md). Earlier isolated P1-P9 receipts remain historical; the correctness consolidation is included in the deployed release. > **Base URL:** `http://localhost:{PORT}/scim` (configurable via `API_PREFIX` env var) > **121 route handlers** across 33 controllers (includes 2 dashboard analytics routes and the web SPA catch-all). Counted from the `@Get`/`@Post`/`@Put`/`@Patch`/`@Delete`/`@Sse` decorators in `api/src/**/*.controller.ts` with comments stripped; the count is enforced by `node scripts/audit-doc-content.mjs`. diff --git a/docs/CONTEXT_INSTRUCTIONS.md b/docs/CONTEXT_INSTRUCTIONS.md index 77db8816..485e546f 100644 --- a/docs/CONTEXT_INSTRUCTIONS.md +++ b/docs/CONTEXT_INSTRUCTIONS.md @@ -1,7 +1,7 @@ # SCIMServer - Context Instructions for AI Assistants > **Purpose**: This file provides complete project context for AI coding assistants (GitHub Copilot, etc.) to enable productive sessions without re-discovery of architecture, patterns, and decisions. -> **Version**: 0.55.64 +> **Version**: 0.55.66 > **Last Updated**: October 29, 2026 > **Last verified:** 2026-10-29 @@ -9,7 +9,31 @@ ## Active Delivery Process -**2026-10-29 current advisory integration:** #260 merged normally at +**2026-10-30 current Hono integration:** #261 merged normally at +`cffc64c8a188a721fabb85c37a80243d5e65a74f`, with all 28 protected gates, +seven exact-head checks and separate technical review. Independent #262 +now integrates that master at its reserved 0.55.66 boundary, preserving +original `7379a97e`, all dependency fixes and both histories below. +New-head graph/restore, protected Validate, clean-CI bytes, independent +review and hosted checks remain mandatory. #251 is unmerged and held by +its verified performance control failure. No deployment/admission follows. +If 0.55.66 merges first, later #251 integration must not downgrade versions. + +**Historical separate adapter preparation:** +**2026-10-29 actual-parent adapter follow-up:** proposed 0.55.66 is +stacked on exact #261 `f4fcfe3ccac83de6548ed9991ed44048ee8d660a`. +[Qualification and RCA](HONO_PRISMA_PARENT_QUALIFICATION.md) records real +Prisma/dev lifecycle with both adapters, security exploit RED/GREEN, and +explicit container cleanup despite inherited post-close process retention. +Existing security pins remain; #251 and reserved 0.55.65 are untouched. +Authenticated CI lock run 40948177653 changes only the API adapter outside +root records. Clean restores retain lock bytes; installed focused GREEN is +6/6 and complete npm inventory exits 0. Final real-parent isolated run passes +all 12 claims and cleans up its container; native invocation fails closed. +Final protected Validate/exact-tip CI remain separate receipts in the ignored +handoff. No external review or overall release proof is inferred. + +**Historical 2026-10-29 advisory integration:** #260 merged normally at `287ea671abf1619d7b172c495310769078bd685b`, after 28/28 protected Validate gates and all seven exact-head checks plus separate technical review. The preserved 0.55.64 advisory branch now integrates that master, including diff --git a/docs/CUSTOM_EXTENSIONS_RFC_GUIDE.md b/docs/CUSTOM_EXTENSIONS_RFC_GUIDE.md index 3faa4cb1..67005f90 100644 --- a/docs/CUSTOM_EXTENSIONS_RFC_GUIDE.md +++ b/docs/CUSTOM_EXTENSIONS_RFC_GUIDE.md @@ -9,7 +9,7 @@ or fetching them. See [minimal-schema validation](GOOGLE_MINIMAL_GROUP_MEMBERSHI [reference persistence and compatibility](GROUP_MEMBER_REFERENCE_PRESERVATION.md) and [release notes](RELEASE_NOTES.md). -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` > **P7a behavior, included since 0.55.36:** [Profile validation](SCIM_P7A_PROFILE_VALIDATION.md) > adds declaration/type/cardinality checks, required extension enforcement, diff --git a/docs/DOCKER_GUIDE_AND_TEST_REPORT.md b/docs/DOCKER_GUIDE_AND_TEST_REPORT.md index e20cb236..ca73645e 100644 --- a/docs/DOCKER_GUIDE_AND_TEST_REPORT.md +++ b/docs/DOCKER_GUIDE_AND_TEST_REPORT.md @@ -1,8 +1,8 @@ # Docker Guide -> **Status:** User-facing reference - **Last verified:** 2026-10-09 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-09 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** June 3, 2026 +> **Version:** 0.55.66 - **Updated:** June 3, 2026 > **Source of truth:** [Dockerfile](../Dockerfile), [docker-compose.yml](../docker-compose.yml) --- diff --git a/docs/ENDPOINT_CONFIG_FLAGS_REFERENCE.md b/docs/ENDPOINT_CONFIG_FLAGS_REFERENCE.md index ae62c558..42630ef9 100644 --- a/docs/ENDPOINT_CONFIG_FLAGS_REFERENCE.md +++ b/docs/ENDPOINT_CONFIG_FLAGS_REFERENCE.md @@ -1,8 +1,8 @@ # Endpoint Configuration Flags Reference -> **Status:** User-facing reference - **Last verified:** 2026-09-29 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-09-29 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** September 29, 2026 +> **Version:** 0.55.66 - **Updated:** September 29, 2026 > **Source of truth:** [endpoint-profile.types.ts](../api/src/modules/scim/endpoint-profile/endpoint-profile.types.ts) (`ProfileSettings`) > 39 registered settings in the unreleased lifetime port: 20 boolean + 16 numeric (11 runtime-egress overrides + 3 active-credential caps + 2 token lifetimes) + 3 other typed values. `PersistRequestSecrets` is inert and `CredentialSecretVisibility` supports only `always`. See the [behavioral evidence and explicit coverage gaps](SCIM_SETTINGS_BEHAVIOR_EVIDENCE.md) and [Entra compatibility guide](SCIM_ENTRA_COMPATIBILITY.md). Registry membership is not evidence of enforcement. > 6 value types: `boolean`, `logLevel`, `primaryEnforcement`, `credentialVisibility`, `structured`, and `number` (the last added for the runtime JWKS-fetch egress knobs). diff --git a/docs/ENDPOINT_CREATION_WIKI.md b/docs/ENDPOINT_CREATION_WIKI.md index 29d7aaff..71f55690 100644 --- a/docs/ENDPOINT_CREATION_WIKI.md +++ b/docs/ENDPOINT_CREATION_WIKI.md @@ -1,8 +1,8 @@ # Create Your Own SCIM Endpoint - Self-Service Wiki -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** 2026-10-16 +> **Version:** 0.55.66 - **Updated:** 2026-10-16 > Beginner-friendly, copy-paste guide for standing up a SCIM endpoint in minutes. > **Source of truth:** [endpoint.controller.ts](../api/src/modules/endpoint/controllers/endpoint.controller.ts) - [built-in-presets.ts](../api/src/modules/scim/endpoint-profile/built-in-presets.ts) diff --git a/docs/ENDPOINT_LIFECYCLE_AND_USAGE.md b/docs/ENDPOINT_LIFECYCLE_AND_USAGE.md index 2de9b3cd..57e47c8d 100644 --- a/docs/ENDPOINT_LIFECYCLE_AND_USAGE.md +++ b/docs/ENDPOINT_LIFECYCLE_AND_USAGE.md @@ -1,8 +1,8 @@ # Endpoint Lifecycle & Usage Guide -> **Status:** User-facing reference - **Last verified:** 2026-10-12 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-12 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** June 3, 2026 +> **Version:** 0.55.66 - **Updated:** June 3, 2026 > Quick-start recipes for common SCIMServer operations --- diff --git a/docs/ENDPOINT_PROFILE_ARCHITECTURE.md b/docs/ENDPOINT_PROFILE_ARCHITECTURE.md index ae92d6fd..32813e61 100644 --- a/docs/ENDPOINT_PROFILE_ARCHITECTURE.md +++ b/docs/ENDPOINT_PROFILE_ARCHITECTURE.md @@ -1,6 +1,6 @@ # Endpoint Profile Architecture -> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.66` > **Updated:** 2026-10-17 > **Source of truth:** [endpoint-profile/](../api/src/modules/scim/endpoint-profile/) and [endpoint.service.ts](../api/src/modules/endpoint/services/endpoint.service.ts) diff --git a/docs/GLOBAL_NAVIGATION_AND_WORKFLOW_CONTEXT.md b/docs/GLOBAL_NAVIGATION_AND_WORKFLOW_CONTEXT.md index 3642fb18..6a7cd57a 100644 --- a/docs/GLOBAL_NAVIGATION_AND_WORKFLOW_CONTEXT.md +++ b/docs/GLOBAL_NAVIGATION_AND_WORKFLOW_CONTEXT.md @@ -1,6 +1,6 @@ # Global navigation and workflow context -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` See [current release notes](RELEASE_NOTES.md) for deployment and acceptance boundaries. Endpoints now uses available window height, Dashboard uses compact diff --git a/docs/HONO_PRISMA_PARENT_QUALIFICATION.md b/docs/HONO_PRISMA_PARENT_QUALIFICATION.md new file mode 100644 index 00000000..069162f0 --- /dev/null +++ b/docs/HONO_PRISMA_PARENT_QUALIFICATION.md @@ -0,0 +1,225 @@ +# Hono adapter: actual Prisma parent qualification + +**Last verified:** 2026-10-29 + +## Executive summary + +**Current integration (2026-10-30):** PR #261 merged normally at `cffc64c8`. +The preserved Hono #262 head `7379a97e` now integrates that reviewed master +through an ordinary merge, retaining the already reserved 0.55.66 version +and all qualification evidence. New-head graph/restore checks, protected +Validate, clean-CI lock bytes, separate technical review and exact-head CI +remain mandatory. This does not clear performance #251 or admit a release. +If merged first, 0.55.66 must not later be downgraded by held 0.55.65. +Preservation now passes: API manifests/locks and qualification fixtures equal +original `7379a97e`; the only non-root package change against reviewed master +is the already-qualified Hono adapter. Web graph equals master, serving +source/schema/estate are preserved. Owned API-only clean restore preserves +both source locks, both complete installed inventories exit 0, and isolated +Prisma generation passes. No repeat real-parent workload was needed because +its complete qualified API graph and source are unchanged. + +**Historical preparation:** proposed 0.55.66 originally branched from draft +#261, exact base `f4fcfe3ccac83de6548ed9991ed44048ee8d660a`. +It selects `@hono/node-server` 2.1.3 only after executing the installed +Prisma parent's real lifecycle with both 1.19.15 and 2.1.3. The affected +adapter returns a synthetic protected file through the published exploit; +2.1.3 returns 404. This is bounded compatibility evidence, not acceptance +by the parent's declared dependency range. + +The public parent shutdown promise resolves and every tested listener and +stateless data file is released with both adapters. Neither version's +process naturally exits in the observed window. The runner explicitly +records that state, stops its exact owned container, verifies it stopped, +and removes it. No `forceExit`, global timer patch, parent monkeypatch, +shared database, cloud resource, or host listener is used. + +No review, merge, deployed-version change, performance qualification, +latest-image admission, or release completion is claimed. Product 0.55.65 +and performance draft #251 remain reserved and untouched. + +## What actually owns the adapter + +```text +prisma 7.8.0 + -> exact @prisma/dev 0.24.3 + -> upstream exact @hono/node-server 1.19.11 + -> project override 1.19.15 before / 2.1.3 proposed + +real startPrismaDevServer() + -> primary PGlite + shadow PGlite + local Streams + -> real Hono application + Node http.createServer + adapter serve() + -> health / authentication error / database dump HTTP requests + -> real close() + port-rebind and stateless-file assertions + -> explicit isolated-container cleanup +``` + +This flow uses the installed parent without replacing its Hono application, +database components, or adapter call with an illustrative fixture. +The adapter's `overrideGlobalObjects: false`, listening callback, Node HTTP +server creation and the parent's public `PortNotAvailableError` remain +exercised. The occupied-port test reaches the public rejection path; it does +not claim to force the narrower race inside the adapter's `EADDRINUSE` +event handler. + +## Advisory and upstream assessment + +| Question | Observed evidence | +|---|---| +| Advisory | [GHSA-rmxm-3fg6-px4f](https://github.com/advisories/GHSA-rmxm-3fg6-px4f), medium, affects `>=1.19.10 <2.1.3`. | +| Mechanism | `serveStatic` decodes a routed path again. A malformed percent-encoded path can avoid prefix authentication while still resolving a protected file inside the configured root. This is not traversal outside the root. | +| First patch | 2.1.3, published at raw UTC `2026-09-29T06:10:34Z`, over seven days old at qualification. | +| Actual fix | [Commit 9821792](https://github.com/honojs/node-server/commit/982179278529d5673812116b042829f27794966f) rejects percent signs remaining in the routed path by default, before rewriting/resolving static files. `allowPercentInPath` is an explicit opt-in. | +| Major-version cost | [v2.0.0](https://github.com/honojs/node-server/releases/tag/v2.0.0) retains the public API but rewrites request/response internals. Node >=20 and unchanged signatures alone were insufficient evidence. | +| Parent patch alternative | Prisma 7.8.0 pins dev 0.24.3 exactly. Earlier same-line dev releases retain affected 1.x requirements. Metadata for later 0.24.x releases omits the direct adapter field, which is not proof of absence from their resolved graphs. No unrelated Prisma upgrade is selected. | +| Scope of exposure | The inspected actual parent uses `serve`, not `serveStatic`. The fix is still applied to the installed affected package; no development-only or reachability suppression is introduced. | + +Existing qs, fast-uri, shared-context, and other security overrides remain. +This closes the final record in the prior six-record assessment, not every +possible advisory in the repository. + +### Worked security example + +The synthetic static server protects `/static/admin/*` with a 401 response +and then serves `/static/*`. Normal public reads still return 200. Both +`/static/admin/secret.txt` and `/static/%61dmin/secret.txt` return 401. + +| Request | Adapter 1.19.15 | Adapter 2.1.3 | +|---|---|---| +| `/static/%%36%31dmin/secret.txt` | 200, synthetic protected file exposed | 404, no protected file | + +The old-version HTTP assertion fails on `200 !== 404`. The permanent Jest +regression also fails on that precise assertion before manifest edits. +Neither test uses customer data. + +## Real parent comparison and permanent checks + +The final baseline comparison first clean-restored the exact #261 API +graph. An earlier installed performance graph had old qs/fast-uri entries; +its successful smoke is retained as preliminary evidence, not substituted +for the restored comparison. + +| Claim | Actual baseline 1.19.15 | Candidate 2.1.3 | +|---|---|---| +| Real parent initialization, HTTP readiness callback | PASS | PASS | +| `GET /health`, status/content type/exact `{ name }` body | PASS | PASS | +| Unknown route, exact 404 body | PASS | PASS | +| `POST /query` without API key, 401 `Missing API Key` | PASS | PASS | +| Primary and shadow synthetic table/insert/select | PASS | PASS | +| `POST /database/dump`, 201, only `dumpPath`, nonempty file | PASS | PASS | +| Global Fetch/Request/Response identities unchanged | PASS | PASS | +| Real close promise resolves; HTTP/primary/shadow/Streams ports rebind | PASS | PASS | +| Occupied requested port rejects with public error and exact port | PASS | PASS | +| Stateless data files removed | PASS | PASS | +| Natural process exit after close | NOT PROVEN; retained process | NOT PROVEN; same retained process | +| Owned container stopped, verified stopped and removed | PASS | PASS | + +The comparison ran Node 24.16.0 in existing `node:24-alpine`, network `none`, +no published ports, read-only dependency mounts and root filesystem, with +only a unique owned evidence directory writable. A read-only adapter-package +mount selected candidate bytes without changing any parent file. + +Permanent regressions cover the selected pin, every locked occurrence, +public resolved URL/SHA-512, real installed Prisma/dev identity and original +constraint, actual owner resolution, adapter exports/global-object contract, +the security exploit with normal-routing controls, and the complete unfiltered +installed npm inventory. The permanent lifecycle runner is separate from the +unit suite so ordinary Jest never starts an actual Prisma development server. +The fixture refuses native invocation before loading its parent. It requires +the runner's explicit flag, a Linux container marker, and internal-only network +interfaces. The final clean-installed run passed all 12 lifecycle claims and +stopped/removed its exact owned container; the native refusal check failed +closed as expected. + +```powershell +# Set DOCKER_CONFIG in this process only if the local recovery profile is needed. +pwsh -NoProfile -File scripts\qualify-prisma-hono-parent.ps1 + +# Before changing the pin, compare an extracted, approved-feed candidate: +pwsh -NoProfile -File scripts\qualify-prisma-hono-parent.ps1 ` + -ExpectedAdapter 1.19.15 +pwsh -NoProfile -File scripts\qualify-prisma-hono-parent.ps1 ` + -ExpectedAdapter 2.1.3 ` + -AdapterPath '\package' +``` + +Do not treat this as all-input compatibility. Native Windows parent +listeners, real external PostgreSQL, accelerated authenticated query-engine +downloads, concurrency/load, arbitrary streaming bodies and production +traffic are not qualified here. The test deliberately needs no network and +does not download engines or contact a cloud estate. + +## Lock provenance and consolidation + +Only the existing clean-runner `regen-lockfile.yml` may generate source +lockfiles. Import requires exact source/ref, artifact ID, authenticated archive +SHA-256, package age, public registry resolved URLs, SHA-512 entries, an +adapter-only API graph delta, and no non-root web graph delta. Approved-feed +tarball bytes must match the imported public lock integrity. Local +`package-lock-only`, feed rewriting and quarantine exceptions are forbidden. + +Clean-runner workflow `40948177653`, exact source +`38b1a781eed63905d429feef2480c899dd203161`, produced artifact `12929363808`. +The authenticated archive SHA-256 is +`bf1c5791b9cfddf1a9e22beacd71a4549835c3d37ebf32db413e0d4629048946`. +The API lock changes only the adapter outside its root record; the web lock +changes no non-root record. Both clean installs retained byte-identical locks, +Prisma client generation reported 7.8.0, and approved-feed adapter bytes match +the imported public SHA-512. The public publication timestamp remains the raw +UTC string `2026-09-29T06:10:34.512Z`. + +The final permanent suite passes 6/6 in one suite, targeted ESLint passes, +and the complete unfiltered installed API npm inventory exits 0 with empty +stderr. Bootstrap protected Fast passed 25/25 gates, including 6,248 API +unit tests in 215 suites and 2,514 HTTP E2E tests (42 existing skipped). +Those bootstrap counts do not include the six permanent tests restored at +lock consolidation. Final protected Validate and exact-tip hosted runs are +separate pending publication evidence, not inferred from that earlier run. +The ignored +`test-results/hono-parent-qualification-20261029/HANDOFF.md` records their +actual commands, counts and immutable receipts after consolidation. + +## Execution issues and root-cause ledger + +| Issue / severity | Symptom and mechanism | Resolution and why | Detection / earliest gate | +|---|---|---|---| +| Working-tree graph mismatch / Medium | Installed performance graph retained qs 6.16.0 and fast-uri 4.1.5 although the stacked #261 manifest requires their patches. Full npm inventory returned `ELSPROBLEMS`. | Ownership helper verified private physical directories; clean `npm ci` restored the exact #261 lock before the final old/new comparison. Same installed parent identity alone does not establish a correct complete graph. | New inventory regression / ownership plus installed-graph preflight. | +| Parent process retention / Medium | Old and new parents release ports and data after real close, but keep a process alive. Preliminary containers required explicit stop; no root cause inside the parent/runtime is claimed. | Separate happy-only and public-error-path runs showed retention in both. Permanent runner records actual pre-cleanup state, then stops/verifies/removes its exact owned container. This bounds resources without modifying the parent or pretending natural exit passed. | Actual lifecycle probe / same probe. | +| Upstream comparison lookup / Low | A fresh `v1.19.15...v2.1.3` GitHub comparison returned 404. | Read the fresh security commit and published v2.0.0/v2.1.3 release records instead; npm package metadata and verified bytes remain the identity evidence. An absent tag is not an absent fix. | Metadata intake / same intake. | +| Lockless bootstrap graph drift / High | An attempted selected-package `npm install --no-package-lock --no-save` re-resolved compatible ranges: installed Prisma became 7.10.1/dev 0.24.17 instead of locked 7.8.0/dev 0.24.3. Source locks remained byte-identical. | Discarded the privately owned wrong graph, clean-restored the exact parent manifest/lock in owned scratch state, then installed only verified candidate tarball bytes into that graph. Regenerated the client at actual 7.8.0 and complete npm inventory exited 0. Final consolidation still requires clean `npm ci` from CI-generated locks. | Post-install real-parent identity check / same check before any compatibility claim. | +| Transitional source CI / Low | Bootstrap image run `40948154638` rejected the deliberately stale lock: 1.19.15 does not satisfy 2.1.3. The source must first be published for the existing CI-only lock workflow. | Exact-source regeneration run `40948177653` succeeded; imported its authenticated minimal artifact and clean-restored both workspaces. This is a transitional failed run, not final-tip success or a waived install gate. | Hosted install / source-lock consistency check; expected until artifact import. | +| Evidence replay baseline / Low | Rerunning the pre-import lock comparison after import reported zero changed records, correctly failing its expected one-record delta. Its mutable baseline was now the imported artifact itself. | Pinned the comparison to bootstrap commit `38b1a78` and separately require current source bytes to equal the authenticated artifact. Baseline identity and import identity are now independent assertions. | Local evidence replay / immutable-baseline check before reuse. | +| Process-local validation environment / Low | The first protected Validate passed 6,254 unit and 2,514 E2E tests, then Prisma generation rejected a missing `DATABASE_URL`. The earlier generation shell's process-local value did not persist into the push shell. | The unchanged generate command passed after deriving the exact checked-in `build-test.yml` CI value without printing it. Repeat that derivation in the same process as the normal Validate push; no database connection, global configuration or gate change is required. | Protected generate gate / process-environment preflight before push. | +| Integration ownership invocation / Low | The first integration invocation omitted the ownership helper's mandatory `RepositoryRoot` argument and stopped before dependency mutation. | Pass the explicit exclusively owned root. All six directory checks report physical ownership; the API-only clean restore then succeeds with both lock hashes unchanged. Keep the explicit argument in subsequent commands rather than relying on current-directory inference. | Parameter binding / same invocation preflight; no detection-stage escape. | + +**Completeness provenance:** this ledger was reconciled with every command +and diagnosed failure in this bounded execution, including preliminary +graph smoke, RED assertions, resource retention and lookup friction. It is +not a claim to have re-audited the parent release's historical transcript. + +The bootstrap lesson is concrete: preserving a source lock does not mean +an install command used that lock. Full npm inventory validity does not +mean installed versions match the graph that was qualified. Do not repeat +lockless broad installation as a shortcut for the CI-only lock workflow. + +## Self-improvement and design disposition + +- **Applied:** a major transitive override now has real-owner identity, + actual old-byte exploit RED, complete installed inventory, and a reusable + isolated real-parent lifecycle/cleanup check. An illustrative adapter + example alone cannot satisfy that claim. +- **Applied:** validation process setup must be repeated in the push shell. + A successful earlier generation process is not evidence that a later shell + inherited its environment. +- **Accepted:** natural process exit remains unqualified and explicit. The + proposed adapter does not fix a pre-existing parent/runtime retention + behavior; no unrelated parent internals or Jest worker settings change. +- **Architecture disposition - accepted:** one dependency pin plus a small + owned-resource test runner is cohesive. No production service/controller + responsibility or coupling changes. A strategy framework would be + speculative. +- **Remaining holds:** actual external review; stack/order reconciliation + before integration with #251; historical performance failure and skipped + draft performance campaigns; operator visual verification, customer-data + and cleanup-403 holds; native/renderer and user-stopped authentication holds; + explicit customer-production approval. diff --git a/docs/INDEX.md b/docs/INDEX.md index 2d668242..072e076e 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -1,8 +1,8 @@ # SCIMServer Documentation Index -> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** 2026-10-21 +> **Version:** 0.55.66 - **Updated:** 2026-10-21 > 6 presets - **39 endpoint settings controls** in the unreleased lifetime port (20 boolean flags + 3 other typed settings + 16 numerics) - profile-driven User, Group, and custom ResourceType forms **Unreleased preparation:** [endpoint token lifetime integration and original @@ -11,6 +11,10 @@ current-master port from earlier isolated validation and deployed behavior. ### Start here +**Pending actual-parent adapter remediation:** [Hono and real Prisma lifecycle qualification](HONO_PRISMA_PARENT_QUALIFICATION.md) +records proposed 0.55.66, actual old/new lifecycle and exploit RED/GREEN, +explicit cleanup boundaries, and a separate draft stacked on unmerged #261. + **Pending stacked API advisory remediation:** [Actual consumer compatibility and RCA](API_ADVISORY_CONSUMER_COMPATIBILITY.md) records proposed 0.55.64, five targeted advisory records and the unchanged Hono adapter blocker. Its draft base is unmerged #260, not master. diff --git a/docs/LOGGING_AND_OBSERVABILITY.md b/docs/LOGGING_AND_OBSERVABILITY.md index 9b0b4ba9..a495246e 100644 --- a/docs/LOGGING_AND_OBSERVABILITY.md +++ b/docs/LOGGING_AND_OBSERVABILITY.md @@ -1,6 +1,6 @@ # Logging & Observability Guide -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` **Current UI presentation:** absolute timestamps in Logs, Activity, Operations and live/detail drawers include full UTC date/time and milliseconds. Copy diff --git a/docs/MULTI_ENDPOINT_GUIDE.md b/docs/MULTI_ENDPOINT_GUIDE.md index 8f68e453..d8c5699d 100644 --- a/docs/MULTI_ENDPOINT_GUIDE.md +++ b/docs/MULTI_ENDPOINT_GUIDE.md @@ -1,8 +1,8 @@ # Multi-Endpoint Architecture Guide -> **Status:** User-facing reference - **Last verified:** 2026-09-28 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-09-28 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** June 3, 2026 +> **Version:** 0.55.66 - **Updated:** June 3, 2026 > **Source of truth:** [endpoint.service.ts](../api/src/modules/endpoint/services/endpoint.service.ts) --- diff --git a/docs/OBSERVABILITY_TRACEABILITY_AND_DIAGNOSTICS.md b/docs/OBSERVABILITY_TRACEABILITY_AND_DIAGNOSTICS.md index d4b36895..3509376e 100644 --- a/docs/OBSERVABILITY_TRACEABILITY_AND_DIAGNOSTICS.md +++ b/docs/OBSERVABILITY_TRACEABILITY_AND_DIAGNOSTICS.md @@ -1,6 +1,6 @@ # Observability, Traceability, Correlation IDs, Logging, Error Handling and Diagnostics -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` **Current operator presentation:** all absolute UI timestamps carry complete UTC date/time, milliseconds and timezone; invalid expiry values are explicit, diff --git a/docs/PATCH_OPERATIONS_COMPLETE_GUIDE.md b/docs/PATCH_OPERATIONS_COMPLETE_GUIDE.md index d23dcfd9..07487400 100644 --- a/docs/PATCH_OPERATIONS_COMPLETE_GUIDE.md +++ b/docs/PATCH_OPERATIONS_COMPLETE_GUIDE.md @@ -11,7 +11,7 @@ rejected later operation saves no earlier mutation. See [reference persistence and rollback compatibility](GROUP_MEMBER_REFERENCE_PRESERVATION.md) and [current release notes](RELEASE_NOTES.md). -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` > Comprehensive, source-verified reference for every PATCH option, mode, setting, path form, verb, and persistence outcome across Users, Groups, custom extensions, and custom resource types - grounded in RFC 7644 / RFC 7643 and the SCIMServer implementation. diff --git a/docs/PROD_TO_DEV_MIRRORING_AND_FIXTURES.md b/docs/PROD_TO_DEV_MIRRORING_AND_FIXTURES.md index 5e62c937..b1e86e56 100644 --- a/docs/PROD_TO_DEV_MIRRORING_AND_FIXTURES.md +++ b/docs/PROD_TO_DEV_MIRRORING_AND_FIXTURES.md @@ -1,8 +1,8 @@ # Prod -> Dev mirroring + synthetic shape-coverage fixtures -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Date:** May 6, 2026 +> **Version:** 0.55.66 - **Date:** May 6, 2026 > **Scope:** dev-tooling, no API surface change > **Affects:** [api/src/scripts/mirror-prod-to-dev.ts](../api/src/scripts/mirror-prod-to-dev.ts), [api/src/scripts/seed-shape-coverage.ts](../api/src/scripts/seed-shape-coverage.ts), [scripts/mirror-prod-to-dev.ps1](../scripts/mirror-prod-to-dev.ps1) diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index a658c69c..23772239 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # SCIMServer release notes -> **Status:** User-facing reference - **Last verified:** 2026-10-23 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-23 - **Product version:** `0.55.66` These curated notes explain what changes for operators and integrators, how to upgrade, and what remains limited. The [engineering changelog](../CHANGELOG.md) @@ -15,7 +15,28 @@ notes rather than assuming that a patch label makes every rollback lossless. ## Unreleased -### Current source consolidation: 0.55.64 +### Current source consolidation: 0.55.66 + +Reviewed #259, #260 and #261 are merged, most recently at `cffc64c8`. +The separate Hono actual-parent correction now integrates that master while +preserving original `7379a97e` and its qualification. Both roots retain the +reserved 0.55.66 version. New-head validation, lock confirmation, review and +hosted checks remain required. This is not a merged or deployed release. +Performance #251 remains held; historical preparations below are provenance. + +### Actual Prisma parent adapter preparation: 0.55.66 + +The [actual-parent qualification report](HONO_PRISMA_PARENT_QUALIFICATION.md) +records proposed `@hono/node-server` 2.1.3, stacked on unmerged draft #261. +Real old/new Prisma initialization, synthetic requests/database writes, +public shutdown and isolated cleanup precede the proposed override. +The exact upstream 1.x constraint remains a documented exception. +Natural parent-process exit is not claimed: both versions retained a process +after releasing the tested listeners and data, and the runner stopped its +owned containers explicitly. No operator migration or API contract change. +This is not a reviewed, merged, deployed or performance-qualified release. + +### Historical source consolidation: 0.55.64 Reviewed web #259 and API inventory #260 are merged, most recently at `287ea671`. The proposed 0.55.64 advisory patch now integrates that master, diff --git a/docs/REMOTE_DEBUGGING_AND_DIAGNOSIS.md b/docs/REMOTE_DEBUGGING_AND_DIAGNOSIS.md index b347938e..fc6478cc 100644 --- a/docs/REMOTE_DEBUGGING_AND_DIAGNOSIS.md +++ b/docs/REMOTE_DEBUGGING_AND_DIAGNOSIS.md @@ -1,6 +1,6 @@ # Remote Debugging & Diagnosis Guide -> **Status:** User-facing reference - **Last verified:** 2026-10-09 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-09 - **Product version:** `0.55.66` > **Version:** 3.2 - **Source-verified against:** v0.55.36 - **Updated:** 2026-10-01 > Request-history identity and authenticated stream transport re-verified against v0.55.36 on 2026-10-01; the full line-by-line pass dates from v0.53.0. diff --git a/docs/SCHEMA_ATTRIBUTE_CUSTOMIZATION_GUIDE.md b/docs/SCHEMA_ATTRIBUTE_CUSTOMIZATION_GUIDE.md index eb755499..45f96e69 100644 --- a/docs/SCHEMA_ATTRIBUTE_CUSTOMIZATION_GUIDE.md +++ b/docs/SCHEMA_ATTRIBUTE_CUSTOMIZATION_GUIDE.md @@ -1,6 +1,6 @@ # Schema Attribute Customization Guide -> **Status:** User-facing reference - **Last verified:** 2026-09-28 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-09-28 - **Product version:** `0.55.66` > **Version**: 1.1 - **Date**: 2026-08-04 - **Status**: Complete (PATCH merge semantics re-verified against `mergeProfilePartial()` on 2026-08-04; the full line-by-line source pass dates from v0.40.0) > **Audience**: Operators, ISV admins, Entra ID integration engineers diff --git a/docs/SCHEMA_CUSTOMIZATION_GUIDE.md b/docs/SCHEMA_CUSTOMIZATION_GUIDE.md index d88c8845..7bc9edc1 100644 --- a/docs/SCHEMA_CUSTOMIZATION_GUIDE.md +++ b/docs/SCHEMA_CUSTOMIZATION_GUIDE.md @@ -10,7 +10,7 @@ effective mutability and response projection. See [reference persistence and migration compatibility](GROUP_MEMBER_REFERENCE_PRESERVATION.md) and [release notes](RELEASE_NOTES.md). -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` > **P7a correctness, included since 0.55.36:** [Declaration and POST/PUT validation](SCIM_P7A_PROFILE_VALIDATION.md) > documents the source changes below, with owned PostgreSQL/InMemory evidence. diff --git a/docs/SOVEREIGN_AND_GOV_CLOUD_DEPLOYMENT.md b/docs/SOVEREIGN_AND_GOV_CLOUD_DEPLOYMENT.md index 10b9a654..9d9ebc8c 100644 --- a/docs/SOVEREIGN_AND_GOV_CLOUD_DEPLOYMENT.md +++ b/docs/SOVEREIGN_AND_GOV_CLOUD_DEPLOYMENT.md @@ -1,8 +1,8 @@ # SCIMServer - Sovereign & Government Cloud Deployment Guide -> **Status:** User-facing reference - **Last verified:** 2026-08-12 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-08-12 - **Product version:** `0.55.66` -> **Version:** 0.55.64 - **Updated:** April 28, 2026 +> **Version:** 0.55.66 - **Updated:** April 28, 2026 > Covers: Azure Government (US), Azure China (21Vianet), Azure BLEU (France), Azure Germany, and custom sovereign environments --- diff --git a/docs/UI_GUIDE.md b/docs/UI_GUIDE.md index fc90e824..f232b4ff 100644 --- a/docs/UI_GUIDE.md +++ b/docs/UI_GUIDE.md @@ -1,8 +1,8 @@ # SCIMServer Web Admin UI Guide -> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.66` -> **Status:** Active | **Last Updated:** 2026-10-16 | **Version:** 0.55.64 +> **Status:** Active | **Last Updated:** 2026-10-16 | **Version:** 0.55.66 > Single-page React + Fluent UI v9 admin console. Nine pages, one shared app shell, live SSE log stream. > **Endpoint/profile/authentication flows:** [PORTABLE_ENDPOINT_PROFILE_AUTHENTICATION_AND_DISCOVERY_DESIGN.md](PORTABLE_ENDPOINT_PROFILE_AUTHENTICATION_AND_DISCOVERY_DESIGN.md) distinguishes the current Create, Discovery, Connect, endpoint Settings, and global Settings surfaces from the target profile-import workflow. > **Screenshot provenance:** every image below was re-captured on **2026-07-31** from the live **dev** estate (then `scimserver-dev.proudbush-ae90986e.eastus.azurecontainerapps.io`) running **v0.55.6 / Node v24.18.1**, at a pinned 1440x900 viewport, using: diff --git a/docs/strategy/ENGINEERING_LESSONS_AND_PATTERNS.md b/docs/strategy/ENGINEERING_LESSONS_AND_PATTERNS.md index 446ac63e..b3eb7510 100644 --- a/docs/strategy/ENGINEERING_LESSONS_AND_PATTERNS.md +++ b/docs/strategy/ENGINEERING_LESSONS_AND_PATTERNS.md @@ -14,6 +14,30 @@ --- +## Real-parent evidence for transitive major overrides (2026-10-29) + +**Applied in:** [Hono adapter qualification](../HONO_PRISMA_PARENT_QUALIFICATION.md). +A transitive dependency's unchanged exported function names do not prove +compatibility when its parent pins an older major and the implementation +rewrites request/response internals. Exercise the installed parent's real +initialization, requests, errors and public close contract in an owned, +network-isolated environment before changing the override. + +Keep package-level exploit RED/GREEN distinct from parent compatibility. +Verify the complete installed graph before the comparison, not just the +named parent package. Measure port/data cleanup separately from natural +process exit, and record explicit owned-resource teardown rather than +hiding a retained process with `forceExit`. Here both adapters retained a +post-close process, so natural exit remains unqualified while the public +close, listener release and stateless-file assertions passed. + +`npm install --no-package-lock --no-save ` is not a +bounded selected-package update: it can re-resolve other semver ranges. +An observed bootstrap moved Prisma 7.8.0 to 7.10.1 without touching the +source lock. Compare installed identities against the qualified lock after +every dependency operation; `npm ls --all` exiting 0 is not that comparison. +Use clean CI-generated source locks and `npm ci` for final assurance. + ## 1. The self-improvement loop (how this doc is fed and used) ### A parent-compatible dependency patch needs actual consumer evidence diff --git a/scripts/fixtures/prisma-hono-parent.cjs b/scripts/fixtures/prisma-hono-parent.cjs new file mode 100644 index 00000000..6edcc088 --- /dev/null +++ b/scripts/fixtures/prisma-hono-parent.cjs @@ -0,0 +1,122 @@ +'use strict'; +const assert = require('node:assert/strict'); +const fs = require('node:fs/promises'); +const net = require('node:net'); +if (process.env.SCIM_HONO_ISOLATED !== '1' || process.platform !== 'linux' || + !require('node:fs').existsSync('/.dockerenv') || + Object.values(require('node:os').networkInterfaces()).flat().some(address => !address.internal)) { + throw new Error('Actual parent qualification requires the network-isolated container runner.'); +} +const { Client } = require('pg'); +const { startPrismaDevServer, PortNotAvailableError } = require('@prisma/dev'); +const path = require('node:path'); +const packageJson = name => require(path.join(path.dirname(require.resolve(name)), '..', 'package.json')); + +async function bind(port) { + const server = net.createServer(); + await new Promise((resolve, reject) => { + server.once('error', reject); + server.listen(port, '127.0.0.1', resolve); + }); + return server; +} +async function close(server) { + await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())); +} +async function main() { + const adapter = packageJson('@hono/node-server'); + assert.equal(require('prisma/package.json').version, '7.8.0'); + assert.equal(packageJson('@prisma/dev').version, '0.24.3'); + assert.equal(adapter.version, process.env.EXPECT_ADAPTER); + const name = 'scim-hono-qualification-20261029'; + const original = { Request: globalThis.Request, Response: globalThis.Response, fetch: globalThis.fetch }; + let server; + const clients = []; + try { + server = await startPrismaDevServer({ + name, persistenceMode: 'stateless', + port: 55113, databasePort: 55114, shadowDatabasePort: 55115, + }); + const streamsPort = Number(new URL(server.experimental.streams.serverUrl).port); + console.log('READY', JSON.stringify({ + adapter: adapter.version, parent: '0.24.3', prisma: '7.8.0', + http: server.http.url, experimental: Object.keys(server.experimental), + })); + for (const [key, value] of Object.entries(original)) assert.equal(globalThis[key], value); + const url = new URL(server.http.url); + url.hostname = '127.0.0.1'; + const health = await fetch(new URL('/health', url)); + assert.equal(health.status, 200); + assert.match(health.headers.get('content-type'), /application\/json/); + assert.deepEqual(await health.json(), { name }); + const missing = await fetch(new URL('/qualification-missing', url)); + assert.equal(missing.status, 404); + assert.equal(await missing.text(), '404 Not Found'); + const invalid = await fetch(new URL('/query', url), { + method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}', + }); + assert.equal(invalid.status, 401); + console.log('HTTP_ERROR', invalid.status, await invalid.text()); + for (const purpose of ['database', 'shadowDatabase']) { + const client = new Client({ connectionString: server[purpose].connectionString }); + clients.push(client); + await client.connect(); + await client.query('CREATE TABLE qualification (id integer primary key, label text not null)'); + await client.query('INSERT INTO qualification VALUES ($1, $2)', [1, 'synthetic-only']); + assert.deepEqual((await client.query('SELECT id, label FROM qualification')).rows, + [{ id: 1, label: 'synthetic-only' }]); + await client.end(); + clients.pop(); + console.log('DATABASE_OK', purpose); + } + const dump = await fetch(new URL('/database/dump', url), { method: 'POST' }); + assert.equal(dump.status, 201); + const payload = await dump.json(); + assert.deepEqual(Object.keys(payload), ['dumpPath']); + assert.equal(typeof payload.dumpPath, 'string'); + assert.ok((await fs.stat(payload.dumpPath)).size > 0); + console.log('DUMP_OK'); + await server.close(); + server = undefined; + for (const port of [55113, 55114, 55115, streamsPort]) await close(await bind(port)); + console.log('SHUTDOWN_PORTS_RELEASED'); + console.log('RESOURCES_AFTER_CLOSE', process.getActiveResourcesInfo()); + const blocker = await bind(55113); + try { + await assert.rejects(startPrismaDevServer({ + name: name + '-conflict', persistenceMode: 'stateless', + port: 55113, databasePort: 55214, shadowDatabasePort: 55215, + }), error => error instanceof PortNotAvailableError && error.port === 55113); + console.log('PORT_CONFLICT_OK'); + } finally { + await close(blocker); + } + for (const port of [55113, 55214, 55215]) await close(await bind(port)); + const dataFiles = await fs.readdir(process.env.XDG_DATA_HOME, { recursive: true, withFileTypes: true }) + .catch(error => { + if (error.code === 'ENOENT') return []; + throw error; + }); + assert.deepEqual(dataFiles.filter(entry => entry.isFile()), []); + console.log('PASS actual installed Prisma parent lifecycle', adapter.version); + console.log('RESOURCES_AFTER_ERROR', process.getActiveResourcesInfo()); + await fs.writeFile('result.json', JSON.stringify({ + passed: true, adapter: adapter.version, prisma: '7.8.0', parent: '0.24.3', + node: process.version, + claims: ['actual-parent-initialization', 'readiness', 'health-body', 'not-found-body', 'query-auth-error', + 'primary-synthetic-write', 'shadow-synthetic-write', 'nonempty-dump', + 'global-fetch-unchanged', 'http-db-shadow-stream-ports-released', + 'occupied-port-rejection', 'stateless-data-files-removed'], + naturalProcessExit: 'not asserted; runner records actual container state before cleanup', + }, null, 2) + '\n'); + } finally { + for (const client of clients) await client.end(); + if (server) await server.close(); + } +} +main().catch(error => { console.error(error); process.exitCode = 1; }).finally(() => { + setTimeout(() => { + console.log('DELAYED_RESOURCES', process.getActiveResourcesInfo()); + console.log('REFERENCED_LIBUV', JSON.stringify(process.report.getReport().libuv.filter(h => h.is_referenced))); + }, 1500).unref(); +}); diff --git a/scripts/qualify-prisma-hono-parent.ps1 b/scripts/qualify-prisma-hono-parent.ps1 new file mode 100644 index 00000000..607f8798 --- /dev/null +++ b/scripts/qualify-prisma-hono-parent.ps1 @@ -0,0 +1,87 @@ +[CmdletBinding()] +param( + [string]$ExpectedAdapter = '2.1.3', + [string]$AdapterPath, + [ValidateRange(30, 180)] + [int]$TimeoutSeconds = 90 +) + +$ErrorActionPreference = 'Stop' +$root = Split-Path $PSScriptRoot -Parent +& (Join-Path $PSScriptRoot 'assert-dependency-ownership.ps1') -RepositoryRoot $root +if ($LASTEXITCODE) { throw 'Dependency ownership preflight failed.' } + +$run = [Guid]::NewGuid().ToString('N') +$name = "scim-hono-qualification-$run" +$state = Join-Path $root "test-results\hono-parent-qualification-20261029\run-$run" +New-Item -ItemType Directory -Path $state | Out-Null +$args = @( + 'create', '--name', $name, '--network', 'none', '--read-only', + '--label', "com.scimserver.hono-qualification=$run", + '--mount', "type=bind,source=$root\api\node_modules,target=/qualification/node_modules,readonly", + '--mount', "type=bind,source=$PSScriptRoot\fixtures,target=/qualification/fixtures,readonly", + '--mount', "type=bind,source=$state,target=/qualification/state", + '--workdir', '/qualification/state', + '--env', 'HOME=/qualification/state/home', + '--env', 'XDG_DATA_HOME=/qualification/state/data', + '--env', 'XDG_CONFIG_HOME=/qualification/state/config', + '--env', 'XDG_CACHE_HOME=/qualification/state/cache', + '--env', 'SCIM_HONO_ISOLATED=1', + '--env', "EXPECT_ADAPTER=$ExpectedAdapter" +) +if ($AdapterPath) { + $adapter = (Resolve-Path -LiteralPath $AdapterPath).Path + $qualificationRoot = Join-Path $root 'test-results\hono-parent-qualification-20261029\' + if (-not $adapter.StartsWith($qualificationRoot, [StringComparison]::OrdinalIgnoreCase)) { + throw 'Candidate adapter must be an extracted package inside the owned qualification evidence directory.' + } + $args += @('--mount', "type=bind,source=$adapter,target=/qualification/node_modules/@hono/node-server,readonly") +} +$args += @('node:24-alpine', 'node', '/qualification/fixtures/prisma-hono-parent.cjs') +$container = $null +try { + $container = (& docker @args | Out-String).Trim() + if ($LASTEXITCODE -ne 0 -or $container -notmatch '^[a-f0-9]{64}$') { + throw 'Could not create the isolated qualification container.' + } + $inspection = & docker inspect $container | ConvertFrom-Json + if ($LASTEXITCODE -ne 0 -or $inspection[0].Name -ne "/$name" -or + $inspection[0].Config.Labels.'com.scimserver.hono-qualification' -ne $run -or + $inspection[0].HostConfig.NetworkMode -ne 'none' -or + $inspection[0].HostConfig.PortBindings.PSObject.Properties.Count -gt 0) { + throw 'Container ownership or network isolation verification failed.' + } + $inspection | ConvertTo-Json -Depth 30 | Set-Content (Join-Path $state 'container.json') + & docker start $container | Out-Null + if ($LASTEXITCODE -ne 0) { throw 'Container startup failed.' } + $deadline = [DateTimeOffset]::UtcNow.AddSeconds($TimeoutSeconds) + $resultPath = Join-Path $state 'result.json' + while (-not (Test-Path -LiteralPath $resultPath)) { + if ([DateTimeOffset]::UtcNow -gt $deadline) { throw "Parent qualification exceeded $TimeoutSeconds seconds." } + $status = & docker inspect --format '{{.State.Running}}' $container + if ($LASTEXITCODE -ne 0 -or $status -ne 'true') { throw 'Parent exited before completing its lifecycle assertions.' } + Start-Sleep -Seconds 1 + } + $result = Get-Content -Raw -LiteralPath $resultPath | ConvertFrom-Json + if ($result.passed -ne $true -or $result.adapter -ne $ExpectedAdapter -or $result.claims.Count -ne 12) { + throw 'Incomplete or mismatched parent qualification result.' + } + Start-Sleep -Seconds 2 + & docker inspect --format '{{json .State}}' $container | + Set-Content (Join-Path $state 'state-before-cleanup.json') + Write-Host "PASS: actual parent lifecycle assertions completed. Evidence: $state" + Write-Host 'Natural process exit is not asserted. Any retained process is explicitly stopped below.' +} finally { + if ($container -match '^[a-f0-9]{64}$') { + & docker logs $container *> (Join-Path $state 'parent.log') + & docker stop --timeout 5 $container | Out-Null + if ($LASTEXITCODE -ne 0) { throw "Could not stop owned container $container." } + $stopped = & docker inspect --format '{{.State.Running}}' $container + if ($LASTEXITCODE -ne 0 -or $stopped -ne 'false') { throw "Owned container $container is still running." } + & docker inspect --format '{{json .State}}' $container | + Set-Content (Join-Path $state 'state-after-cleanup.json') + & docker rm $container | Out-Null + if ($LASTEXITCODE -ne 0) { throw "Could not remove owned container $container." } + Write-Host "CLEANUP: stopped and removed exact owned container $container." + } +} diff --git a/web/package-lock.json b/web/package-lock.json index 2e22e7e9..a6a86591 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "scimserver-web", - "version": "0.55.64", + "version": "0.55.66", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scimserver-web", - "version": "0.55.64", + "version": "0.55.66", "dependencies": { "@fluentui/react-components": "^9.74.2", "@fluentui/react-icons": "^2.0.331", diff --git a/web/package.json b/web/package.json index 244537d3..bff93836 100644 --- a/web/package.json +++ b/web/package.json @@ -1,7 +1,7 @@ { "name": "scimserver-web", "private": true, - "version": "0.55.64", + "version": "0.55.66", "type": "module", "scripts": { "dev": "vite",