Merged PR 2430: Add API grouping facade rollout checkpoint

Add API grouping facade rollout checkpoint

Related work items: #23754
This commit is contained in:
Robert Bond
2026-06-25 09:05:59 +00:00
parent a266fa5428
commit f9f78548b0
3 changed files with 229 additions and 0 deletions
+59
View File
@@ -259,6 +259,65 @@ It means:
- excluded adjacent search journeys remain unchanged
- no route migration, deletion, or contract change has occurred
#### API Grouping Façade Rollout Checkpoint
- The first successful façade slices now establish a proven additive rollout pattern for:
- subscriptions / watched cases
- documents / published document metadata
- public search results
- Proven runtime shape:
```text
UI journey
→ existing service layer
→ grouped façade route
→ legacy canonical handler
→ unchanged integration behaviour
```
- Proven implementation pattern:
- audit the active journey path first
- identify the existing owning/common service layer already used by that path
- add grouped façade routes only for the proven in-scope active calls
- implement each grouped route as a tiny wrapper that delegates directly to the existing legacy handler
- keep the legacy handler as the canonical implementation
- adopt the grouped route in the existing service layer only where the active journey path is proven and low-risk
- leave adjacent, inactive, support, or orchestration-heavy routes out of scope unless separately justified
- prove the slice with lightweight characterization tests covering delegation, service adoption, retained legacy handlers, and unchanged scope boundaries
- Important interpretation:
- this checkpoint proves a safe rollout pattern for additive façade grouping
- it does not approve route removal
- it does not approve handler replacement
- it does not approve broad migration
- it does not approve grouping of more complex API families without another bounded audit
#### Vertical façade slice completion criteria
- A vertical façade slice should be treated as complete only when:
- active journey paths are audited
- grouped façade routes exist for the in-scope active routes only
- the service layer adopts the grouped routes where safe and proven
- legacy handlers remain present and canonical behind the façade
- inactive or support routes are explicitly left out of scope where they are not part of the active adopted path
- characterization tests prove façade delegation and service-layer adoption
- characterization tests do not imply that legacy handlers can be removed
- documentation records the exact scope, completion meaning, exclusions, and non-goals
- A slice is not complete merely because grouped files exist.
- Completion requires both bounded adoption evidence and explicit documentation of what remains outside scope.
#### Do not group yet criteria
- Grouping should be delayed when any of the following apply:
- no clear service layer exists
- active ownership is unclear
- the route is orchestration-heavy
- the route crosses storage + queue + CRM boundaries
- the route is auth/session critical
- the route is not proven active in a bounded current journey
- grouping would require frontend refactor rather than additive service-level adoption
- grouping would require contract change
- In these cases, documentation may still classify the area conceptually, but additive façade rollout should wait for a safer bounded slice.
---
### Stage 3 — Documentation Maturity
+67
View File
@@ -20,6 +20,73 @@ Follow-ups:
### CL-2026-06-25-API-GROUPING-FACADE-SEARCH-VERTICAL-SLICE: active public search results grouping and service adoption
### CL-2026-06-25-API-GROUPING-FACADE-ROLLOUT-CHECKPOINT: proven rollout pattern and guardrails checkpoint
date: 2026-06-25
author: Cline
scope: `context/api-grouping-adoption-roadmap.md`, `tests/phase22/api-grouping-facade-rollout.test.cjs`, `memory-bank/change-log.md`
type: milestone
rationale: Record a short checkpoint after the first successful additive API grouping façade slices so the proven rollout pattern, completion criteria, and delay/guardrail criteria are documented before considering more complex API groups.
impact: Documentation and characterization only; no runtime behaviour, handler implementation, service URL, route location, payload, contract, auth/session behaviour, or integration behaviour change.
status: completed
Summary:
- Confirmed the required checkpoint context was read before implementation:
- `context/api-grouping-plan.md`
- `context/api-grouping-adoption-roadmap.md`
- `context/api-route-map.md`
- `context/portal-api-platform-assessment.md`
- `context/architecture.md`
- `memory-bank/change-log.md`
- existing façade tests under `tests/phase22`
- Confirmed the proven slice pattern now established by the completed façade areas:
- `pages/api/subscriptions/*`
- `pages/api/documents/*`
- `pages/api/search/*`
- Recorded the rollout checkpoint in the adoption roadmap with the proven shape:
- UI journey
- existing service layer
- grouped façade route
- legacy canonical handler
- unchanged integration behaviour
- Documented completion criteria for a vertical façade slice, including:
- bounded active-journey audit
- grouped façade coverage for in-scope active routes only
- safe service-layer adoption
- retained canonical legacy handlers
- explicit out-of-scope treatment for inactive/support routes
- characterization proof and scope documentation
- Documented “do not group yet” criteria for cases such as:
- unclear ownership
- missing clear service layer
- orchestration-heavy routes
- storage + queue + CRM crossing routes
- auth/session-critical routes
- unproven activity
- required frontend refactor
- required contract change
- Added a lightweight meta-test to characterize the checkpoint structure without introducing a larger framework.
Validation:
- Focused validation only for this checkpoint:
- `npx eslint tests/phase22/api-grouping-facade-rollout.test.cjs`
- `node tests/phase22/api-grouping-facade-rollout.test.cjs`
- `node tests/phase22/api-grouping-facade-subscriptions.test.cjs`
- `node tests/phase22/api-grouping-facade-documents.test.cjs`
- `node tests/phase22/api-grouping-facade-search.test.cjs`
- No heavy repo-wide tooling run.
Follow-ups:
- Use this checkpoint as the baseline before considering any further façade candidates.
- Prefer the next candidate only where the same additive pattern can be proven without route movement, contract change, or orchestration-risk expansion.
---
### CL-2026-06-25-API-GROUPING-FACADE-SEARCH-VERTICAL-SLICE: active public search results grouping and service adoption
date: 2026-06-25
author: Cline
scope: `pages/api/search/basic-paged.js`, `pages/api/search/advanced.js`, `pages/api/search/advanced-paged.js`, `pages/api/search/basic-details-paged.js`, `actions/services/searchDirectService.js`, `tests/phase22/api-grouping-facade-search.test.cjs`, `context/api-grouping-adoption-roadmap.md`
@@ -0,0 +1,103 @@
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const rootDir = path.resolve(__dirname, "..", "..");
const tests = [];
const test = (name, fn) => tests.push({ name, fn });
const exists = (relativePath) =>
fs.existsSync(path.join(rootDir, relativePath));
const read = (relativePath) =>
fs.readFileSync(path.join(rootDir, relativePath), "utf8");
test("known grouped facade folders exist for proven slices", async () => {
[
"pages/api/subscriptions",
"pages/api/documents",
"pages/api/search"
].forEach((folderPath) => {
assert.strictEqual(exists(folderPath), true, folderPath);
});
});
test("known façade characterization test files exist", async () => {
[
"tests/phase22/api-grouping-facade-subscriptions.test.cjs",
"tests/phase22/api-grouping-facade-documents.test.cjs",
"tests/phase22/api-grouping-facade-search.test.cjs"
].forEach((filePath) => {
assert.strictEqual(exists(filePath), true, filePath);
});
});
test("existing slice tests cover service adoption or retained scope checks", async () => {
const subscriptionsSource = read(
"tests/phase22/api-grouping-facade-subscriptions.test.cjs"
);
const documentsSource = read(
"tests/phase22/api-grouping-facade-documents.test.cjs"
);
const searchSource = read(
"tests/phase22/api-grouping-facade-search.test.cjs"
);
assert.match(
subscriptionsSource,
/portalDirectService watched-case methods now target subscriptions facade routes/
);
assert.match(
documentsSource,
/searchDirectService document journey methods now target grouped documents facade routes/
);
assert.match(
searchSource,
/searchDirectService active public search methods now target grouped search routes/
);
assert.match(
searchSource,
/excluded routes remain outside grouped public search adoption scope/
);
});
test("checkpoint tests do not imply legacy handlers can be removed", async () => {
const sliceSources = [
read("tests/phase22/api-grouping-facade-subscriptions.test.cjs"),
read("tests/phase22/api-grouping-facade-documents.test.cjs"),
read("tests/phase22/api-grouping-facade-search.test.cjs")
].join("\n");
assert.doesNotMatch(sliceSources, /legacy handlers can be removed/i);
assert.doesNotMatch(sliceSources, /delete legacy/i);
assert.match(sliceSources, /legacy .* remain/i);
const roadmapSource = read("context/api-grouping-adoption-roadmap.md");
assert.match(roadmapSource, /does not approve route removal/i);
assert.match(
roadmapSource,
/legacy handlers remain present and canonical/i
);
});
async function run() {
let failures = 0;
for (const { name, fn } of tests) {
try {
await fn();
console.log(`${name}`);
} catch (error) {
failures += 1;
console.error(`${name}`);
console.error(error);
}
}
if (failures > 0) {
process.exit(1);
}
}
run();