diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3cf5bf..104c2cdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### 0.55.64 reviewed-master integration (2026-10-29) + +- Normally integrate reviewed master `287ea671` after #259 and #260 merged. + Preserve every original advisory commit and both preparation histories. + Retain qs 6.16.1, fast-uri 4.2.3, the four API root override contexts and + merged web Seroval 1.6.11 / Undici 7.30.1. No new runtime implementation. +- Parent #260 passed 28/28 protected Validate gates and seven exact-head + checks, with independent technical review. Those results are provenance, + not substitutes for this integration's protected gates or hosted CI. +- Both roots remain at the already reserved 0.55.64. Confirm the + coordinated lock graph in clean CI without local lock regeneration. + No new test/gate improvement identified: existing installed-owner, + complete-inventory and graph-union checks cover the integration. + Design accepted: ordinary history-preserving merge, no new abstraction. + No deployment, full advisory clearance or performance admission. + +### 0.55.64 preparation - compatible API advisory pins, stacked on draft #260 + +- Reserve 0.55.64 after checking existing branches, pull requests and releases. + Keep the exact #260 ancestry; do not merge or retarget either draft. +- Select qs 6.16.1 and fast-uri 4.2.3 to address five of the six assessed + advisory records. Leave `@hono/node-server` 1.19.15 unchanged because + compatibility with the actual Prisma development lifecycle is unproved. +- Add 19 actual-consumer and advisory-boundary regressions: pre-manifest RED is 11 + failures / three passes. Existing Ajv compiler, Express parser, Superagent + serializer and body-parser stream behavior already pass at baseline. +- [Public changes, actual ownership, advisory boundaries and execution RCA](docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md). + Authenticated CI run 40923567650 changes exactly two API entries and no + non-root web entry; approved-feed bytes match locked SHA-512. Clean restore + keeps both lock hashes identical and full API npm inventory exits 0. + Final restored focus: 57/57 in three suites, up from 38 parent checks. + Bootstrap units 6,229/214 suites and HTTP 2,514/118 passing suites retain + 42 existing skipped tests and two skipped suites. Final broad protected + Validate counts are recorded in the handoff after execution; + no deployed release claim. + ### 0.55.63 reviewed-master integration (2026-10-29) - Normally integrate web #259's merged master `0a9b3d04` into the preserved diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 4ee6e8a6..9105c409 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` > Updated: 2026-10-16 - Scope: production + local deployment paths diff --git a/README.md b/README.md index 1c998d3a..49190d0a 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` > Production-ready, multi-tenant SCIM 2.0 server for Microsoft Entra ID provisioning and any RFC 7643/7644-compliant identity client. @@ -9,9 +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 source-only inventory correction:** [API override-context validity](docs/API_OVERRIDE_CONTEXT_VALIDITY.md) -describes proposed 0.55.63 and the complete-tree npm regression. It changes -no application behavior and does not qualify a deployment or clear the +**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. + +**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 +changes no application behavior and does not qualify a deployment or clear the separately tracked API security advisories. For actual supported shapes and integration limits, see @@ -20,7 +25,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.63-blue)]() +[![Version](https://img.shields.io/badge/version-0.55.64-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 5f002da5..e14dba7d 100644 --- a/Session_starter.md +++ b/Session_starter.md @@ -2,7 +2,47 @@ **Last verified:** 2026-10-29 -### Current reviewed-master integration (2026-10-29) +### Current advisory integration (2026-10-29) + +PR #260 merged normally at `287ea671abf1619d7b172c495310769078bd685b` +after 28/28 protected Validate gates, seven successful exact-head checks and +separate technical review. API units were 6,229, HTTP 2,514 plus 42 existing +skips, and web 1,661 across 125 files. PR #259 is also merged. + +The existing 0.55.64 branch now normally integrates that reviewed master, +preserving all constituent commits. Its qs 6.16.1 and fast-uri 4.2.3 changes +remain separate from the Hono correction and performance tooling. Both +historical preparation sections below are retained, not current status. +Installed-graph verification, coordinated clean-CI lock confirmation, +protected Validate, refreshed review and exact-head CI still own this head. +Parent-union manifests/locks pass with zero non-root drift; clean API restore +preserves both lock hashes and both complete npm inventories exit 0. +No application, auth, UI, schema, deployment or release-admission change. +All performance, data/restore, live/browser and operator-visual holds remain. + +| Date | Summary | +|---|---| +| 2026-10-29 | Normally merge reviewed API #260 at 0.55.63, then integrate its master into preserved advisory #261 at 0.55.64; new-head proof remains required. | + +### Historical stacked API advisory remediation (2026-10-29) + +Proposed 0.55.64 starts from exact draft #260 head +`6eb1b59cb1a8ea324bb1a32b17355fabc605279d` on +`fix/api-advisory-pins-20261029`. Only qs 6.16.1 and fast-uri 4.2.3 +are selected. Actual consumers are three qs owners and nested Ajv 8.20.0; +its pre-existing forced major remains explicitly outside `^3.0.1`. +Corrected RED before manifest edits: 11 failed, three passed, 14 tests. +[Compatibility, advisory boundaries and RCA](docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md) +records why Hono 2.1.3 remains blocked by unproved actual Prisma lifecycle +compatibility. No service is started and no other worktree is owned. +CI-only run 40923567650, artifact 12918583682, changes exactly two API entries +and no non-root web entry. Approved-feed bytes match authenticated SHA-512; +clean API/web restores keep both lock hashes identical. Initial restored +focus is 57/57 in three suites including 19 new checks; complete npm +inventory exits 0 without problems. Final protected Validate remains required. +PR #259/#260 are unmerged, #251 and every existing hold remain unchanged. + +### Historical reviewed-master integration for 0.55.63 (2026-10-29) PR #259 merged normally as `0a9b3d04535dc51dcfc58e9a2360c1c9e112a41a` after successful exact-head CI and a separate read-only technical review. diff --git a/api/package-lock.json b/api/package-lock.json index 9bca935b..8efa1d0f 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -1,12 +1,12 @@ { "name": "scimserver-api", - "version": "0.55.63", + "version": "0.55.64", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scimserver-api", - "version": "0.55.63", + "version": "0.55.64", "license": "MIT", "dependencies": { "@nestjs/common": "^11.1.27", @@ -4640,9 +4640,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.5.tgz", - "integrity": "sha512-vZeoMRB4epNr7QfdHxel7te/RcX16CxyXI07JCCTFWZA2s4v1azGNESRj+2EoaHSaWFL/Z3GmKT2jF6A202jLg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.2.3.tgz", + "integrity": "sha512-I1PXwP5eAhlNlcdpjt9CgB59op2ZvZfxw+BkqGFVIUOgNpCVTcTqp3HhTX7brxj5vsip+nSY4nTvff+eIA76hg==", "devOptional": true, "funding": [ { @@ -7436,9 +7436,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", - "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.1.tgz", + "integrity": "sha512-5Px6J7rfHBAGUhNQ3es4YzcOdBBw0SDcVtThJml4RdnKw4tKs2epA0kPZ+K8X+WiHktT93RHVcQ/3ym5aTCgtg==", "license": "BSD-3-Clause", "dependencies": { "es-define-property": "^1.0.1", diff --git a/api/package.json b/api/package.json index 5398e614..2ec131ea 100644 --- a/api/package.json +++ b/api/package.json @@ -1,6 +1,6 @@ { "name": "scimserver-api", - "version": "0.55.63", + "version": "0.55.64", "description": "SCIMServer backend service providing SCIM 2.0 endpoints and logging for troubleshooting.", "license": "MIT", "main": "dist/main.js", @@ -84,7 +84,7 @@ "@hono/node-server": "1.19.15", "defu": "6.1.5", "effect": "3.20.0", - "fast-uri": "4.1.5", + "fast-uri": "4.2.3", "hono": "4.13.11", "multer": "2.5.0", "deepmerge-ts": "8.0.0", @@ -110,7 +110,7 @@ "js-yaml": "3.15.2", "node-releases": "2.0.57", "proxy-addr": "2.0.8", - "qs": "6.16.0", + "qs": "6.16.1", "valibot": "1.4.2" } } diff --git a/api/src/scripts/check-api-advisory-consumers.spec.ts b/api/src/scripts/check-api-advisory-consumers.spec.ts new file mode 100644 index 00000000..8eec2b0c --- /dev/null +++ b/api/src/scripts/check-api-advisory-consumers.spec.ts @@ -0,0 +1,220 @@ +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { Readable } from 'node:stream'; +import { satisfiesGhsaRange } from './check-dependency-pins'; + +type Package = { + version: string; + dependencies?: Record; + resolved?: string; + integrity?: string; +}; +type Uri = { + parse(value: string): { scheme?: string; host?: string; error?: string }; + normalize(value: string, options?: { reference: string }): string; + serialize(value: { path: string; scheme?: string }, options?: { reference: string }): string; + resolve(base: string, relative: string): string; +}; +type Query = { + parse(value: string, options?: Record): unknown; + stringify(value: unknown, options?: Record): string; +}; + +const apiRoot = resolve(__dirname, '../..'); +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 semver = require('semver') as { satisfies(version: string, range: string): boolean }; +const ajvOwner = 'node_modules/@prisma/streams-local/node_modules/ajv'; +const consumerModule = (owner: string, name: string): string => + require.resolve(name, { paths: [resolve(apiRoot, owner)] }); +const uri = require(consumerModule(ajvOwner, 'fast-uri')) as Uri; + +describe('API advisory pins and actual installed consumers', () => { + it.each([ + ['GHSA-6pq8-jhm2-2vcw', '6.16.0', '6.16.1', '>= 6.7.0, <= 6.16.0'], + ['GHSA-w74x-v6f9-j3xg', '4.1.5', '4.2.3', '>= 4.0.0, < 4.2.3'], + ['GHSA-xhq7-xmqj-769h', '4.1.5', '4.2.3', '>= 4.0.0, < 4.2.3'], + ['GHSA-wjr9-j795-jxcr', '4.1.5', '4.2.3', '>= 4.0.1, < 4.2.3'], + ['GHSA-333x-w4r6-6crp', '4.1.5', '4.2.3', '>= 4.0.0, < 4.2.3'], + ])('checks both sides of the published %s boundary', (_id, before, patched, range) => { + expect(satisfiesGhsaRange(before, range)).toBe(true); + expect(satisfiesGhsaRange(patched, range)).toBe(false); + }); + + it.each([ + ['qs', '6.16.1', '>= 6.7.0, <= 6.16.0'], + ['fast-uri', '4.2.3', '>= 4.0.0, < 4.2.3'], + ])('pins every %s occurrence outside its advisory boundary', (name, version, range) => { + expect(manifest.overrides[name]).toBe(version); + const occurrences = Object.entries(lock.packages).filter(([path]) => + path === `node_modules/${name}` || path.endsWith(`/node_modules/${name}`), + ); + expect(occurrences.map(([path]) => path)).toEqual([`node_modules/${name}`]); + for (const [, entry] of occurrences) { + expect(entry.version).toBe(version); + expect(satisfiesGhsaRange(entry.version, range)).toBe(false); + expect(entry.resolved).toBe(`https://registry.npmjs.org/${name}/-/${name}-${version}.tgz`); + expect(entry.integrity).toMatch(/^sha512-[A-Za-z0-9+/]+=*$/); + } + }); + + it('resolves every declared qs owner to the compatible installed patch', () => { + const owners = Object.entries(lock.packages).flatMap(([path, entry]) => + entry.dependencies?.qs ? [[path, entry.dependencies.qs]] : [], + ); + expect(owners).toEqual([ + ['node_modules/body-parser', '^6.16.1'], + ['node_modules/express', '^6.14.0'], + ['node_modules/superagent', '^6.14.1'], + ]); + for (const [path, range] of owners) { + const owner = JSON.parse(readFileSync(resolve(apiRoot, path, 'package.json'), 'utf8')) as Package; + expect(owner.dependencies?.qs).toBe(range); + expect(semver.satisfies('6.16.1', range)).toBe(true); + const installedPath = consumerModule(path, 'qs/package.json'); + expect(installedPath).toBe(resolve(apiRoot, 'node_modules/qs/package.json')); + expect((JSON.parse(readFileSync(installedPath, 'utf8')) as Package).version).toBe('6.16.1'); + } + }); + + it('records the real Ajv owner and does not mistake an existing forced major for semver acceptance', () => { + const owners = Object.entries(lock.packages).flatMap(([path, entry]) => + entry.dependencies?.['fast-uri'] ? [[path, entry.dependencies['fast-uri']]] : [], + ); + expect(owners).toEqual([[ajvOwner, '^3.0.1']]); + const owner = JSON.parse(readFileSync(resolve(apiRoot, ajvOwner, 'package.json'), 'utf8')) as Package; + expect(owner.version).toBe('8.20.0'); + expect(owner.dependencies?.['fast-uri']).toBe('^3.0.1'); + expect(semver.satisfies('4.2.3', '^3.0.1')).toBe(false); + const installedPath = consumerModule(ajvOwner, 'fast-uri/package.json'); + expect(installedPath).toBe(resolve(apiRoot, 'node_modules/fast-uri/package.json')); + expect((JSON.parse(readFileSync(installedPath, 'utf8')) as Package).version).toBe('4.2.3'); + }); + + it.each(['body-parser', 'express', 'superagent'])( + 'keeps %s query parsing and serialization correct and handles non-callable comma elements', + owner => { + const qs = require(consumerModule(`node_modules/${owner}`, 'qs')) as Query; + expect(qs.parse('filter=userName%20eq%20%22Ada%22&attributes=userName%2Cname&startIndex=1')) + .toEqual({ filter: 'userName eq "Ada"', attributes: 'userName,name', startIndex: '1' }); + expect(qs.parse('profile[name]=Ada&tags[]=one&tags[]=two&__proto__[polluted]=yes', { + allowPrototypes: true, + depth: 32, + arrayLimit: 100, + })).toEqual({ profile: { name: 'Ada' }, tags: ['one', 'two'] }); + expect(qs.stringify({ filter: 'userName eq "Ada"', attributes: ['userName', 'name'] })) + .toBe('filter=userName%20eq%20%22Ada%22&attributes%5B0%5D=userName&attributes%5B1%5D=name'); + expect(qs.stringify({ values: [{ toString: 'not callable' }] }, { + arrayFormat: 'comma', + })).toBe('values=%5Bobject%20Object%5D'); + }, + ); + + it('uses the real Express query parser and Superagent form serializer', () => { + const express = require('express') as { + (): { + set(name: string, value: string): void; + get(name: string): (input: string) => unknown; + }; + }; + const app = express(); + app.set('query parser', 'extended'); + expect(app.get('query parser fn')('filter=active%20eq%20true&name[givenName]=Ada')) + .toEqual({ filter: 'active eq true', name: { givenName: 'Ada' } }); + const superagent = require('superagent') as { + serialize: Record string>; + }; + expect(superagent.serialize['application/x-www-form-urlencoded']({ + filter: 'active eq true', attributes: ['userName', 'name'], + })).toBe('filter=active%20eq%20true&attributes=userName&attributes=name'); + }); + + it('parses a real body-parser URL-encoded request stream without opening a server', async () => { + const body = 'profile[name]=Ada&tags[]=one&tags[]=two&__proto__[polluted]=yes'; + const request = Object.assign(Readable.from([Buffer.from(body)]), { + headers: { + 'content-type': 'application/x-www-form-urlencoded', + 'content-length': String(Buffer.byteLength(body)), + }, + method: 'POST', + body: undefined, + }); + const bodyParser = require('body-parser') as { + urlencoded(options: { extended: boolean }): ( + req: typeof request, response: object, next: (error?: Error) => void + ) => void; + }; + await new Promise((complete, reject) => { + bodyParser.urlencoded({ extended: true })(request, {}, error => error ? reject(error) : complete()); + }); + expect(request.body).toEqual({ profile: { name: 'Ada' }, tags: ['one', 'two'] }); + }); + + it('compiles external, relative, fragment and recursive references with the actual nested Ajv', () => { + const Ajv = require(resolve(apiRoot, ajvOwner)) as new (options: Record) => { + opts: { uriResolver: Uri }; + addSchema(schema: unknown): void; + compile(schema: unknown): ((data: unknown) => boolean) & { + errors: { instancePath: string; keyword: string }[] | null; + }; + }; + const ajv = new Ajv({ allErrors: true }); + expect(ajv.opts.uriResolver).toBe(uri); + ajv.addSchema({ + $id: 'https://schemas.example/common.json', + definitions: { + name: { type: 'string', minLength: 2 }, + node: { + type: 'object', + properties: { name: { $ref: '#/definitions/name' }, child: { $ref: '#/definitions/node' } }, + required: ['name'], + additionalProperties: false, + }, + }, + }); + const validate = ajv.compile({ + $id: 'https://schemas.example/team/user.json', + type: 'object', + properties: { profile: { $ref: '../common.json#/definitions/node' } }, + required: ['profile'], + additionalProperties: false, + }); + expect(validate({ profile: { name: 'Ada', child: { name: 'Grace' } } })).toBe(true); + expect(validate({ profile: { name: 'A', child: { name: 7 }, extra: true } })).toBe(false); + expect(validate.errors).toEqual(expect.arrayContaining([ + expect.objectContaining({ instancePath: '/profile/name', keyword: 'minLength' }), + expect.objectContaining({ instancePath: '/profile/child/name', keyword: 'type' }), + expect.objectContaining({ instancePath: '/profile', keyword: 'additionalProperties' }), + ])); + expect(() => ajv.compile({ $ref: 'missing.json#/absent' })).toThrow(/resolve reference/); + }); + + it('rejects encoded schemes through the actual Ajv URI resolver', () => { + expect(uri.parse('%6Aavascript:alert(1)').error).toBe('URI scheme is malformed.'); + expect(uri.normalize('%6Aavascript:alert(1)')).toBe('%6Aavascript:alert(1)'); + expect(() => uri.resolve('https://schemas.example/', '%u006Aavascript:alert(1)')).toThrow(); + }); + + it('preserves relative-reference meaning before actual Ajv URI resolution', () => { + const base = 'https://schemas.example/team/schema.json'; + for (const relative of ['../common.json', 'a/../common.json', './child:part']) { + expect(uri.resolve(base, uri.normalize(relative))).toBe(uri.resolve(base, relative)); + } + expect(uri.normalize('../common.json')).toBe('../common.json'); + }); + + it('rejects host confusion through the actual Ajv URI resolver', () => { + expect(uri.parse('http://a@b@evil.example/').error).toBeDefined(); + expect(uri.parse('http://good\tevil.example/').error).toBeDefined(); + }); + + it('escapes suffix colons through the actual Ajv URI resolver', () => { + const suffix = uri.serialize({ scheme: 'x', path: 'javascript:alert(1)' }, { reference: 'suffix' }); + expect(suffix).toBe('javascript%3Aalert(1)'); + expect(uri.parse(suffix).scheme).toBeUndefined(); + }); +}); diff --git a/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md b/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md new file mode 100644 index 00000000..277c0044 --- /dev/null +++ b/docs/API_ADVISORY_CONSUMER_COMPATIBILITY.md @@ -0,0 +1,208 @@ +# API advisory pins: consumer compatibility and execution RCA + +**Last verified:** 2026-10-29 + +## Executive summary + +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. +Its bounded package changes remain qs 6.16.0 to 6.16.1 and fast-uri 4.1.5 +to 4.2.3, alongside the inherited web and inventory corrections. This +integration is not yet merged or deployed. PR #251 and #262 remain separate. +Historical independent-branch receipts below do not qualify the new head. + +The integrated manifests and complete locks match the intended parent union: +API equals original `f4fcfe3c`, web equals merged `287ea671`, with only +coordinated 0.55.64 root metadata. There is zero non-root drift. Clean API +restore passes with both lock hashes unchanged; the physically unchanged +web graph is retained. Both complete `npm ls --all --json` inventories +exit 0. Clean-CI byte confirmation and new-head gates are still pending. + +Parent #260 passed all 28 protected Validate gates and seven exact-head +hosted checks, with separately executed technical review. This integration +still requires its own installed-graph checks, coordinated clean-CI lock +confirmation, protected Validate, refreshed review and exact-head hosted CI. +No new test/gate improvement is identified: the existing actual-owner, +complete-inventory and graph-union assertions cover this ordinary merge. +Design disposition: **accepted**, existing flat pins and preserved histories; +no speculative abstraction or new application responsibility. + +The six-record assessment consists of one qs advisory, four fast-uri +advisories and one Hono adapter advisory. Five records can be corrected +with bounded consumer evidence. The Hono adapter remains blocked, not +suppressed. No finding is dismissed because a package is development-only. + +## Actual owners and compatibility boundaries + +| Dependency | Locked and installed owners | Assessment | +|---|---|---| +| qs 6.16.1 | body-parser 2.4.0 requires `^6.16.1`; Express 5.2.1 requires `^6.14.0`; Superagent 10.3.0 requires `^6.14.1` | All three ranges accept the patch. The previous override suppressed body-parser's published minimum. | +| fast-uri 4.2.3 | The only owner is Ajv 8.20.0 nested under `@prisma/streams-local`, requiring `^3.0.1` | This range does NOT accept either the old forced 4.1.5 or new 4.2.3. Compatibility is bounded behavioral evidence through the actual Ajv compiler and its own URI resolver, not semver acceptance. | +| `@hono/node-server` 1.19.15, unchanged | `@prisma/dev` 0.24.3 requires exact 1.19.11 | Patched 2.1.3 is outside the exact requirement. No compatible parent patch has been proved in this rollback unit. | + +```text +Express / body-parser / Superagent -> shared qs 6.16.1 +Prisma streams-local -> actual nested Ajv 8.20.0 -> fast-uri 4.2.3 +Prisma dev 0.24.3 -> node-server 1.19.15 (blocked advisory remains) +``` + +The graph shows actual locked consumers, not a representative replacement +application. The regression enumerates every occurrence and checks installed +owner declarations and the exact module each owner resolves. + +### Public upstream assessment + +- [qs comparison](https://github.com/ljharb/qs/compare/v6.16.0...v6.16.1): + comma-format serialization handles non-callable `toString`; additional + parser, nesting-bound, encoding and strict-merge fixes require testing + parsing as well as serialization. No major API change is claimed. +- [fast-uri comparison](https://github.com/fastify/fast-uri/compare/v4.1.5...v4.2.3): + encoded schemes and invalid hosts are rejected; relative-reference meaning + and suffix colons are preserved. Other changes cover IPv6 zones, mailto, + URN dot segments and invalid references. The public type diff adds optional + `ipv6Zone`, without removing existing resolver methods. This is not a + promise of all-input compatibility: deliberately malformed inputs change. +- [Hono adapter v2 release](https://github.com/honojs/node-server/releases/tag/v2.0.0) + says the public API stays the same, but replaces request/response internals + for performance. Node >=20 is only an engine prerequisite, not proof of + compatibility with a parent pinned to 1.x. +- [Hono patch release](https://github.com/honojs/node-server/releases/tag/v2.1.3) + rejects remaining percent signs after static-path decoding, with an explicit + opt-in for literal percent signs. + +### Why the Hono adapter is blocked + +Installed `@prisma/dev/dist/index.cjs`, `daemon.cjs` and the ESM chunk +`chunk-2O6J3K3T.js` dynamically import `serve`. The actual parent supplies +Node's HTTP `createServer`, its own constructed Hono application's `fetch`, +`overrideGlobalObjects: false` and a port, and awaits the listening callback. +It registers an `EADDRINUSE` error path. Its close operation promisifies +`server.close` and also stops the parent-managed database components. + +This couples compatibility to real parent initialization, request/response +handling, errors and shutdown, not merely the existence of `serve`. A tiny +Hono fixture or a Node engine check cannot prove those claims. The actual +parent lifecycle starts its development database/server; this task forbids +starting applications or databases. No parent/runtime redesign or broad +Prisma upgrade is authorized. Therefore leave the adapter override unchanged, +retain [GHSA-rmxm-3fg6-px4f](https://github.com/advisories/GHSA-rmxm-3fg6-px4f), +and require an isolated, explicitly authorized parent lifecycle qualification +or a minimally compatible upstream Prisma patch before changing it. + +## Advisory boundaries and permanent evidence + +| Advisory | Boundary on selected line | New outcome | +|---|---|---| +| [GHSA-6pq8-jhm2-2vcw](https://github.com/advisories/GHSA-6pq8-jhm2-2vcw) | qs >=6.7.0, <=6.16.0 | 6.16.1 is outside | +| [GHSA-w74x-v6f9-j3xg](https://github.com/advisories/GHSA-w74x-v6f9-j3xg) | fast-uri >=4.0.0, <4.2.3 | 4.2.3 is outside | +| [GHSA-xhq7-xmqj-769h](https://github.com/advisories/GHSA-xhq7-xmqj-769h) | fast-uri >=4.0.0, <4.2.3 | 4.2.3 is outside | +| [GHSA-wjr9-j795-jxcr](https://github.com/advisories/GHSA-wjr9-j795-jxcr) | fast-uri >=4.0.1, <4.2.3 | 4.2.3 is outside | +| [GHSA-333x-w4r6-6crp](https://github.com/advisories/GHSA-333x-w4r6-6crp) | fast-uri >=4.0.0, <4.2.3 | 4.2.3 is outside | +| GHSA-rmxm-3fg6-px4f | adapter >=1.19.10, <2.1.3 | Still present, compatibility blocked | + +New tests in `api/src/scripts/check-api-advisory-consumers.spec.ts` exercise +all three qs resolutions, the real Express configured parser, Superagent's +form serializer and body-parser's request-stream middleware without opening +a server. Comma-format hardening is tested through each owner's resolved qs, +not misrepresented as those parents' default options. + +The actual nested Ajv compiles external, relative, fragment and recursive +schema references. Tests assert valid and invalid data plus exact validation +error locations and keywords and unresolved-reference rejection. They obtain +the URI resolver from the actual Ajv instance and check each advisory +mechanism independently. Existing complete `npm ls --all --json` acceptance +remains mandatory and unfiltered. + +## RED/GREEN and validation + +Before any manifest edit, the corrected actual-consumer run produced +11 real assertion failures and three passes across 14 tests. The three +compatibility paths already passed on old dependencies; exact pins, installed +versions, comma serialization and all four URI mechanisms failed as expected. +Logs are retained under `test-results/api-advisory-pins-20261029/`. + +Follow-up fixture correction distinguishes `parse` returning an error from +`normalize` preserving malformed input, and tests suffix serialization with +an explicit input scheme that is omitted from output. The public advisory's +string-normalization example does not reproduce on the patch. Replaying the +real old 4.1.5 approved-feed bytes produces four URI assertion failures and +one Ajv compiler pass; restoring 4.2.3 passes all five. This is separate from +the original pre-manifest RED, not a rewritten account of it. Comma-format +serialization also asserts the full hardened output, not merely no exception. + +The final regression includes five explicit published advisory boundaries, +for 19 new tests. The first complete authenticated-restore focus passed 52/52 +before adding those boundary assertions, including the existing 38 regressions. +The final focus passes 57/57 in three suites. Lock provenance, documentation +freshness, documentation content and diff whitespace checks also pass. +Protected Validate totals are retained in the handoff after execution. + +### Clean CI lock and restore receipts + +- Unchanged regeneration workflow run + [40923567650](https://github.com/pranems/SCIMServer/actions/runs/40923567650) + uses exact bootstrap source `eb797fd69ef2b371e3a1812198fe6f159eeafc1c`. +- Artifact `12918583682` ZIP SHA-256: + `bb3b81a1a4dd2eeb14f04e4838d50f6f883fae666057d0ece60e05d42ff29edf`. + Authenticated GitHub metadata and downloaded bytes agree. +- API lock SHA-256: + `01c0c63e29db93f5520195d3bfccf3b22fedbe20bcb1ca77effb0bccf136209e`. + Web lock SHA-256: + `b0c972aa28b428439e46913847b5e25ac85ae5395e5ed3ab6078c1ad33e629c9`. +- Exactly two non-root API entries change: qs and fast-uri. Zero non-root + web entries change. Only product/root versions change otherwise. +- Approved-feed tarball bytes match both authenticated locked SHA-512 values. + Missing SHA-512 metadata from the proxy was not treated as success. +- CI measured ages at 2026-10-29T17:40:35.970Z: qs 14.815 days, + fast-uri 9.784 days, both above the unchanged seven-day floor. +- Physical ownership checks precede restore. Clean `npm ci` in API and web + succeeds through the existing corporate registry, with both tracked locks + byte-identical afterwards. The actual complete API inventory exits 0 + with no problems and empty stderr. + +The normal Fast bootstrap push passes 25 gates, 6,229 API units in 214 suites +and 2,514 HTTP tests in 118 passing suites (42 existing skipped tests and two +skipped suites). This bootstrap uses provisional dependencies, not final +qualification. Hosted bootstrap Build Test Image `40923545248` correctly +fails `npm ci` on the two intentionally stale lock entries; its failure +receipt is retained. The final normal Validate push owns broad applicable +gates after the clean CI-lock restore. No PR-to-master matrix is inferred +when the draft uses a stacked base. + +## Execution issues and root-cause analysis + +| ID / type / severity | Symptom and mechanism | Correction and prevention | Detection / earliest possible | +|---|---|---|---| +| AC-1 / test correctness / Low | Initial Superagent fixture called its private query finalizer before the real request builder serializes queued objects. URL stayed unchanged. | Use the actual public form serializer, assert complete values, and retain corrected RED before manifests change. No network request is needed. | First focused RED / same | +| AC-2 / tooling / Low | Comparing Hono v1.19.15 to v2.1.3 returned HTTP 404 because that comparison ref is unavailable. | Read authenticated public v2 release notes and patch release plus actual installed parent bundle. Do not equate failed lookup with compatibility. | Assessment / same | +| AC-3 / test correctness / Medium | Initial URI fixtures assumed normalize throws and that a scheme-free suffix object discriminates the colon defect. The patch preserves malformed input; that object was already safe on old bytes. | Assert parse's actual error, normalization preservation and resolve's throw separately. Supply an explicit omitted output scheme for suffix serialization. Real old-byte replay fails all four mechanisms, while the actual Ajv compiler remains green. | First provisional GREEN / same | +| AC-4 / dependency tooling / Low | Bootstrap install without a lockfile write changed the provisional local tree and left one platform-related extraneous package. | Remove that owned extraneous directory, retain full inventory output, and replace the entire provisional installation with clean npm ci from authenticated CI locks. Bootstrap is never final consumer evidence. No lockfile was generated locally. | Focused inventory / same | +| AC-5 / CI bootstrap / Low | Hosted bootstrap npm ci rejects the deliberately stale qs/fast-uri entries. | Dispatch the existing regeneration workflow from the protected source, authenticate run and archive, allow only the two intended entries, then restore and publish normally. | Hosted install / expected before authenticated artifact | +| AC-6 / documentation / Low | Header freshness repair left the README badge and source-coupled release notes requiring explicit updates. A first index edit assumed the wrong heading. | Use actual headings, update badge and release narrative, then pass existing freshness and content gates. | Bootstrap static audit / same | +| AC-7 / tooling / Low | A source-snippet command had shell quoting error; one guessed documentation command/file did not exist, and gh run view rejected a path JSON field. | Use exact discovered filenames and GitHub REST run metadata for workflow path. Retain failed receipts without interpreting them as package failures. | Assessment / same | +| AC-8 / static quality / Low | The first final-push lint run exposed one new unnecessary type assertion in the request-stream fixture, raising warnings from 507 to 508 despite zero errors. | Stop the owned publication before push, remove the redundant assertion, run focused ESLint, then publish normally with the unchanged protected Validate hook. Preserve the interrupted receipt. No warning ceiling is raised. | Consolidation lint / focused new-file lint could have caught it earlier | + +Provenance: this bounded execution retains raw command logs and public metadata +in the ignored evidence directory. Tool failures, assertion failures and +publication receipts were reconciled against this execution's available +commands and retained logs. `VSCODE_TARGET_SESSION_LOG` is not present, so a +full debug-transcript reconciliation could not be performed and is not claimed. +The original assertion assumptions were corrected as AC-3, not dismissed. +Existing Jest worker/forced-exit warnings and competing-renderer diagnostics +remain inherited holds, not new runtime regressions or resolved problems. + +## Self-improvement and design disposition + +**Applied:** actual-parent owner enumeration, behavioral RED/GREEN, explicit +forced-major rejection and one assertion per advisory mechanism prevent an +engine check or a toy adapter fixture from becoming false compatibility proof. + +**Accepted:** two flat version pins and a focused regression file introduce no +new runtime responsibility, dependency seam or response field. A generalized +resolver abstraction would duplicate existing package tooling without a +second justified implementation. + +Performance, customer-data, cleanup-403, live/browser, visual/native/renderer, +latest-admission and user-stopped authentication holds remain unchanged. +No release-complete, review-approval, deployment or merge claim is made. diff --git a/docs/AUTHENTICATION_GUIDE.md b/docs/AUTHENTICATION_GUIDE.md index 8ad56292..aab5bc39 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.63` +> **Status:** Living reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` > > **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 bbf7575f..c854c113 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-08-12 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** June 3, 2026 +> **Version:** 0.55.64 - **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 91f771a0..1b3e5f13 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** 2026-10-16 +> **Version:** 0.55.64 - **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 7a635eec..77db8816 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.63 +> **Version**: 0.55.64 > **Last Updated**: October 29, 2026 > **Last verified:** 2026-10-29 @@ -9,6 +9,27 @@ ## Active Delivery Process +**2026-10-29 current 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 +merged web #259. Both historical paragraphs below describe earlier states. +Coordinated CI locks, installed graph, new-head protected validation, +refreshed review and hosted checks remain mandatory. No deployment or +final-artifact qualification is implied. + +**Historical independent 0.55.64 preparation:** +**2026-10-29 stacked API advisory remediation:** proposed 0.55.64 is based +on draft #260 exact head `6eb1b59cb1a8ea324bb1a32b17355fabc605279d`, +not master or web #259. [Consumer compatibility and RCA](API_ADVISORY_CONSUMER_COMPATIBILITY.md) +records qs 6.16.1, fast-uri 4.2.3, actual-parent RED and the unchanged +Hono adapter compatibility blocker. Ajv's forced 4.x remains a documented +range exception, not semver acceptance. CI lock run 40923567650 changes only +the two API packages; authenticated archive and approved-feed SHA-512 agree. +Clean restored final focus 57/57, complete inventory exit 0. Protected +Validate is recorded separately after execution. No merge or deploy. + +**Historical 0.55.63 integration preparation:** **2026-10-29 current integration:** reviewed web #259 merged normally at `0a9b3d04535dc51dcfc58e9a2360c1c9e112a41a`. API #260 now integrates that master at its existing 0.55.63 boundary, preserving both histories and diff --git a/docs/CUSTOM_EXTENSIONS_RFC_GUIDE.md b/docs/CUSTOM_EXTENSIONS_RFC_GUIDE.md index 51778634..3faa4cb1 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` > **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 cecc0edc..e20cb236 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-09 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** June 3, 2026 +> **Version:** 0.55.64 - **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 c7e62722..ae62c558 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-09-29 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** September 29, 2026 +> **Version:** 0.55.64 - **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 52ceac36..29d7aaff 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** 2026-10-16 +> **Version:** 0.55.64 - **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 a889c067..2de9b3cd 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-12 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** June 3, 2026 +> **Version:** 0.55.64 - **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 943773c2..ae92d6fd 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` > **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 55556be2..3642fb18 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` 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/INDEX.md b/docs/INDEX.md index 578b9a84..2d668242 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-21 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** 2026-10-21 +> **Version:** 0.55.64 - **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 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. + **Pending independent inventory correction:** [API shared override context validity](API_OVERRIDE_CONTEXT_VALIDITY.md) records proposed 0.55.63, all real owners, full-tree RED/GREEN and the same-version root override correction. The current integration now inherits diff --git a/docs/LOGGING_AND_OBSERVABILITY.md b/docs/LOGGING_AND_OBSERVABILITY.md index e85271f9..9b0b4ba9 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` **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 ad14700f..8f68e453 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-09-28 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** June 3, 2026 +> **Version:** 0.55.64 - **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 c5f64a0d..d4b36895 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` **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 7f705a17..d23dcfd9 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` > 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 f0e7cf80..5e62c937 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Date:** May 6, 2026 +> **Version:** 0.55.64 - **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 bf1b3069..a658c69c 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-23 - **Product version:** `0.55.64` These curated notes explain what changes for operators and integrators, how to upgrade, and what remains limited. The [engineering changelog](../CHANGELOG.md) @@ -15,6 +15,24 @@ notes rather than assuming that a patch label makes every rollback lossless. ## Unreleased +### Current 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, +retaining both fixes and every constituent commit. Its new-head validation, +review and CI remain separate requirements. Historical preparation notes +below remain provenance, not claims about the current merged/deployed state. +The Hono and final-artifact qualification boundaries remain unchanged. + +### Stacked API advisory preparation: 0.55.64 + +The [actual-consumer compatibility report](API_ADVISORY_CONSUMER_COMPATIBILITY.md) +records proposed qs 6.16.1 and fast-uri 4.2.3 pins, stacked on unmerged +draft #260. Five assessed API advisory records are targeted. The Prisma +development adapter advisory remains blocked pending actual-parent lifecycle +qualification; this is not full advisory clearance or a deployed release. +No API response contract, migration or operator configuration changes. + ### 0.55.62 web Seroval and Undici security dependency patch This proposed patch updates exact web overrides from Seroval 1.6.3 to diff --git a/docs/REMOTE_DEBUGGING_AND_DIAGNOSIS.md b/docs/REMOTE_DEBUGGING_AND_DIAGNOSIS.md index 86e5e45e..b347938e 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-09 - **Product version:** `0.55.64` > **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 70c5ce53..eb755499 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-09-28 - **Product version:** `0.55.64` > **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 0b7b652d..d88c8845 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` > **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 f6ff3787..10b9a654 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-08-12 - **Product version:** `0.55.64` -> **Version:** 0.55.63 - **Updated:** April 28, 2026 +> **Version:** 0.55.64 - **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 b3f9636c..fc90e824 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.63` +> **Status:** User-facing reference - **Last verified:** 2026-10-16 - **Product version:** `0.55.64` -> **Status:** Active | **Last Updated:** 2026-10-16 | **Version:** 0.55.63 +> **Status:** Active | **Last Updated:** 2026-10-16 | **Version:** 0.55.64 > 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 f0d7e569..446ac63e 100644 --- a/docs/strategy/ENGINEERING_LESSONS_AND_PATTERNS.md +++ b/docs/strategy/ENGINEERING_LESSONS_AND_PATTERNS.md @@ -16,6 +16,19 @@ ## 1. The self-improvement loop (how this doc is fed and used) +### A parent-compatible dependency patch needs actual consumer evidence + +An engine range only answers whether Node can load a package, not whether an +exact-pinned parent remains correct. Likewise, a pre-existing forced major +does not make the next forced version semver-compatible. Enumerate locked +and installed owners, assess public API changes, and exercise the real +parent's parser/compiler/lifecycle. Preserve successful baseline behavior +alongside discriminating security RED/GREEN. A toy replacement fixture is +not proof for an actual parent's initialization and shutdown. +The [stacked API advisory patch](../API_ADVISORY_CONSUMER_COMPATIBILITY.md) +keeps the Prisma/Hono adapter blocked because those lifecycle claims cannot +be verified under the no-service-start constraint. + ### PowerShell location is not every library's working directory `Set-Location` changes PowerShell's provider location, but a .NET API resolving diff --git a/web/package-lock.json b/web/package-lock.json index 123ae971..2e22e7e9 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "scimserver-web", - "version": "0.55.63", + "version": "0.55.64", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scimserver-web", - "version": "0.55.63", + "version": "0.55.64", "dependencies": { "@fluentui/react-components": "^9.74.2", "@fluentui/react-icons": "^2.0.331", diff --git a/web/package.json b/web/package.json index 9ea22fad..244537d3 100644 --- a/web/package.json +++ b/web/package.json @@ -1,7 +1,7 @@ { "name": "scimserver-web", "private": true, - "version": "0.55.63", + "version": "0.55.64", "type": "module", "scripts": { "dev": "vite",