Files
shopdb-flask/docs/wiki-drafts/README.md
cproudlock f9d6b57f0f Move the documentation to the line that ships, and correct it against the code
The docs lived on one lineage and the fleet code on another. That is why six
pages described a shared fleet key as how an agent authenticates, why
COLLECTOR-AUTH had to warn that the per-PC credential code was not in the
repository it sat in, and why ADR-019 recorded a decision whose implementation
was somewhere else. Documentation that cannot see the code it documents goes
stale by construction, and no amount of editing fixes that.

So the corpus moves here: 84 files, 56 pages, 20 ADRs, the proposals, INDEX.md,
llms.txt and both gates. Filenames are unchanged, because a wiki page name is
derived from the filename and a rename breaks every link anybody saved.

THE POINT OF THE MOVE IS THE CORRECTION IT ENABLES. Every caveat that said "not
in this tree" was false the moment the files landed beside the code, so each was
rewritten from what is actually here:

- COLLECTOR-AUTH gained the real enroll request body, the two bounds on the
  unauthenticated route (per-IP rate limit, pending cap with stale rows dropped
  before a real PC is refused), and the rejected pending reason that binds to
  the endpoint identity rather than the nonce.
- ADR-019 now describes an implementation that is present, including its tests,
  and says plainly that what remains is the FLEET migration, not the code.
- proposals/device-identity claimed phase 1 was unbuilt. plugins/computers
  declares deviceid on the collector schema and prefers it over the older
  fallbacks. Corrected in the page, its summary and the index.

WINDOWS/IIS IS NOW DOCUMENTED AS THE LEGACY PATH, per the product decision, and
carefully: it is what production runs today. Every Windows page opens by saying
it is supported, not for a new site, and where a new site should go instead. No
procedure was cut - an operator on an IIS box at 2am needs these pages to work
exactly as well tomorrow. MIGRATE-TOPOLOGY stops being a footnote and becomes
the off-ramp, which is why it nearly doubled: what was there did not match how
the Docker stack really works here.

The Docker material that already lived on this line was kept and given
ownership rather than buried under the ported Windows-centric prose: DEPLOY now
describes the four services, the migrate service that runs the upgrade chain
before api starts, TLS terminated by nginx, and the plugin count corrected from
thirteen to seventeen - a number both lineages had wrong.

ROADMAP is rewritten from evidence rather than memory: what has shipped, read
out of the changelog, the ADRs and the manifests, and ahead of it exactly two
items - finalize a distributed release and polish the setup wizard.

PROJECT-MAP is generated and was stale; the GENERATOR was what was wrong.
--check passes now.

API-REFERENCE is retired to a pointer. /api/docs serves 573 operations with
derived auth, query parameters and harvested examples, and a hand-written page
competing with that is a liability. The file stays so its wiki page and its
inbound links survive.

AND THE MOVE TURNED ON A SCRUB THAT HAD NEVER RUN HERE. test_docs_publishable
keys on docs/*.md, which this line did not have, so it skipped - its own comment
predicted what would surface. Porting the corpus activated it and it found 48
lines that must not reach a published wiki: branch names abbreviating the site,
assistant-tooling paths, the site name in two deployment pages, and an employee
ID in a Windows path that the scrub does not even look for.
2026-09-19 09:10:15 -04:00

25 KiB

Wiki Page Drafts - 2026-09-11, revised 2026-09-18

Read with the date on it. This is a point-in-time audit, kept as the record of what was found and what it turned out to be, not as current guidance. One thing it says repeatedly is no longer true: it was written when this line carried no ADRs, and the full ADR set now lives beside it in docs/adr. Where this page says a decision record is missing or lives elsewhere, look there first.

This directory contains drafted wiki pages based on work completed Q3 2026. Copy these to the GitHub wiki at https://github.com/ge-aero/shopdb-flask/wiki.

Revised 2026-09-18, the deployment branch at 35d4fcd41. A full review re-checked every page here against the code. Architectural-Findings-2026-09-11.md was substantially wrong and now carries a verdict and evidence per finding. Maintenance-Footprint-Baseline.md is annotated where the tree has moved on. Security-Audit-2026-09-11.md was refreshed with a verdict per finding and thirteen new ones. ADR-019-...md had two internal contradictions corrected. A new page, ADR-Conformance-2026-09-18.md, was added. The SECURITY.md draft below had its ADR-016 section replaced: it described a decision ADR-016 never took and banned the registry storage the reference site fleet depends on. Nothing here is ready to paste without reading the 2026-09-18 notes inside each file first.

New Pages to Create

1. ADR-019: Plugin Dynamic Settings Routes

File: ADR-019-Plugin-Dynamic-Settings-Routes.md
Wiki path: ADRs/ADR-019-Plugin-Dynamic-Settings-Routes
Summary: Documents the get_settings_routes() hook that lets plugins dynamically register settings pages (e.g., Operating Systems in Model Catalog). Fixes lean build failures from hardcoded plugin imports.

Key sections:

  • Problem: Hardcoded imports break lean builds
  • Decision: Backend hook + frontend dynamic route registration
  • Implementation: BasePlugin hook, /api/plugins/settings-routes endpoint, ModelCatalogHub integration
  • Benefits: Lean builds work, plugins self-contain UI, runtime flexibility
  • Constraints as implemented: Model Catalog is the only hub that draws plugin tabs, the tabs are not deep-linkable, and the component is bound at build time

Related commits: fe09d2745e, d59d0c3194

2026-09-18: corrected against the shipped code. The "Backend: API Endpoint" code block showed @jwt_required(optional=True) iterating get_enabled_plugin_instances(); neither exists. It now shows shopdb/core/api/plugins.py:46-95 as it stands, gated on settings.view. The Future Extensions section no longer calls the endpoint anonymous. Everything else in the draft checked out, including the three constraints. Note docs/openapi.json still documents this endpoint as anonymous, so publishing the ADR without regenerating the spec leaves the two disagreeing.


2. Security Audit - September 11, 2026

File: Security-Audit-2026-09-11.md
Wiki path: Security/Security-Audit-2026-09-11
Summary: Comprehensive security review of endpoints plugin, C# agent, and tray app. 4 critical + 6 high vulnerabilities identified. 3 critical fixed, 1 critical planned.

Key findings:

  • CRITICAL FIXED: Unauthenticated inventory updates
  • CRITICAL FIXED: Hardcoded admin credentials
  • CRITICAL FIXED: Collector key exposure in git
  • CRITICAL PLANNED: Certificate validation disabled in agent
  • HIGH: Password exposure in mcp-servers.json (fixed)
  • HIGH: Audit log unbounded growth (planned Q4 2026)
  • PERFORMANCE: 99.9% improvement opportunity with delta updates

Risk matrix: 8 critical + 10 high operational risks
Remediation status: 7 of 18 findings fixed or mitigated


3. Maintenance Footprint Baseline

File: Maintenance-Footprint-Baseline.md
Wiki path: Operations/Maintenance-Footprint-Baseline
Summary: Baseline assessment of operational burden: 936 hrs/year across database management, deployment, Docker, testing, and security. Identifies 147-205 hrs/year savings via automation.

Key metrics:

  • Total burden: 936 hrs/year (23.4 work-weeks)
  • Deployment coordination: 312 hrs/year (air-gap burden)
  • Database management: 234 hrs/year (audit log retention critical)
  • Docker management: 156 hrs/year (log rotation missing)
  • Testing/validation: 130 hrs/year (pre-commit automation)
  • Security/compliance: 78 hrs/year (scanning + updates)

Automation:

  • 13 assistant automation skills created (this figure checks out: ls <assistant-config>/skills/*.md)
  • 147-205 hrs/year saved (from 936 baseline)
  • 7 quick wins identified (4 hours - 6 hours effort each)

Risk matrix: 8 critical + 10 high operational risks

2026-09-18: annotated. Every hour figure and row count on that page is an unsourced estimate and the page now says so. Four recommendations have since been built and the page records what and where: audit-log retention (service, CLI and setting, but default 0 and no scheduler), backups (restic with 5/4/6 retention, SMB and S3 destinations, restore simulation), agent delta updates, and per-endpoint certificate pinning. Three risk-matrix rows were stale and are corrected: certificate validation is not disabled, login rate limiting exists, and the collector fix is per-PC endpoint credentials rather than "device token auth". Docker log rotation is still genuinely missing: grep -c logging docker-compose.yml returns 0.


4. Architectural Findings - September 11, 2026

File: Architectural-Findings-2026-09-11.md
Wiki path: Architecture/Architectural-Findings-2026-09-11
Summary: Gortex semantic code analysis identified 22 architectural issues (6 critical, 6 high, 10 medium). Focus areas: plugin boundaries, dependency management, schema consistency.

Critical findings:

  1. Circular dependencies between plugins (violates ADR-001 isolation)
  2. Undeclared import dependencies (plugins import shopdb.core internals)
  3. Schema drift (SQLAlchemy models != Alembic migrations)
  4. Single points of failure (no HA in production)
  5. Migration chain validation gaps (ADR-008 enforcement)
  6. Implicit database connection sharing (transaction isolation)

High findings: 7. Frontend plugin import violations (ADR-013) 8. Site literals hardcoded in plugins (ADR-015) 9. Missing error handling on external calls 10. No rate limiting, no API versioning, state management inconsistencies

Remediation timeline: Q4 2026 - Q4 2027

2026-09-18: do not publish this page as it stood. Re-checking it against the deployment branch refuted most of it. There is no module-level cross-plugin import anywhere (grep -rn "^from plugins\." plugins/ --include=*.py = 0 hits) and machines does not import computers at all, so finding 1's cycle does not exist. No plugin deep-imports shopdb.core (0 hits), so finding 2 is refuted outright. No migration in the tree spells a column in snake_case, so finding 3's examples are refuted. MACHINE_TYPES, Bldg 300, Vuex, a ServiceNow plugin and an unhandled requests.post do not exist. The page has been rewritten to carry a verdict and the evidence per finding, keeping the four that survive in narrowed form.


5. ADR Conformance - September 18, 2026

File: ADR-Conformance-2026-09-18.md Wiki path: ADRs/ADR-Conformance-2026-09-18 Summary: ADR-by-ADR result of the 2026-09-18 review of the deployment branch at 35d4fcd41. Fourteen ADRs hold with cited evidence; eight items are recorded as violations or gaps, each with a file and line.

Reads first, before the table: the ADR set does not exist on this branch. ls docs/adr fails on the deployment branch; ADR-001 through ADR-018 live only on the other lineage. Nothing here states the rules and nothing here enforces them except scripts/check-naming-and-style.sh, which names exactly two ADRs (ADR-017 at line 343, ADR-015 at line 395). A handful of tests cover ADR ground without saying so, and tests/test_api_inventory_parity.py skips itself entirely because docs/api-inventory.json is not tracked here.

Violations recorded: ADR-007 (CHANGELOG untouched across 20 commits), ADR-008 (endpoints migration 0023 does DDL on core assets), ADR-016 (misdescribed in four files, and the per-PC programme has no design record), ADR-018 (accepted, unimplemented, no status note), ADR-001/002 (raw SQL over core tables in the computers CLI), ADR-015 (the scan does not cover agent/), ADR-002 (two stale manifest floors).


Pages to Update

PLUGIN-DEVELOPMENT.md

Add section: "Plugin Settings Routes"

## Plugin Settings Routes

Plugins can extend core settings hubs (Model Catalog, Asset Config, etc.) by declaring routes via the `get_settings_routes()` hook.

### Example: Operating Systems in Model Catalog

```python
class ComputersPlugin(BasePlugin):
    def get_settings_routes(self) -> List[Dict]:
        return [{
            'hub': 'model-catalog',
            'path': 'operatingsystems',
            'name': 'model-catalog-os',
            'tab': 'Operating Systems',
            'component': '.plugins-staged/computers/views/OperatingSystemsList.vue'
        }]

The frontend fetches routes from /api/plugins/settings-routes and registers them dynamically via router.addRoute().

Rules for declaring one

  1. Declare hub: 'model-catalog' or declare nothing. Model Catalog is the only hub whose page registers plugin tabs. A route naming any other hub (asset-config, security, network, ...) is dropped by the API with an error in the log, because nothing would draw it. For a settings page that belongs elsewhere, own a full page in plugins/<name>/frontend/routes.js instead: it is statically registered and behaves like any other route.
  2. Your frontend must be staged into the build. component is a path relative to frontend/src, so it must be the staged copy - .plugins-staged/<name>/views/X.vue, made by scripts/stage-frontend.mjs from plugins/<name>/frontend/views/X.vue. Enabling the plugin at runtime does not put the file in a bundle that was built without it; that needs a frontend rebuild.
  3. Register the page in your routes.js too, and treat that as the real route. The hub's import of your component is not rewritten by Vite (no static file extension in the template), so it resolves under npm run dev and 404s in a production build. The tab is a convenience on top of a normal plugin route, not a way to ship a page. A gate test enforces this.
  4. Do not link directly to your tab's URL. The hub registers the route when it mounts, so the URL only resolves for someone who reached it through the hub. A bookmark, a link in an email, or a refresh on the tab lands nowhere.

Benefits:

  • Lean builds work (no hardcoded plugin imports)
  • Plugins self-contain their UI extensions
  • Enable/disable changes the tabs, for a plugin already in the build

Reference: ADR-019 Plugin Dynamic Settings Routes, section "Constraints as implemented"


---

### API-REFERENCE.md
**Add endpoint:** `/api/plugins/settings-routes`

```markdown
## GET /api/plugins/settings-routes

Returns settings routes contributed by all enabled plugins via `get_settings_routes()` hook. A route naming a hub that does not draw plugin tabs is dropped, with an error in the server log naming the plugin and the hub.

**Auth:** `settings.view` (it names the enabled plugins, the hub layout and the internal component paths; no pre-login page calls it)

**Response:**
```json
{
  "status": "success",
  "data": {
    "routes": [
      {
        "hub": "model-catalog",
        "path": "operatingsystems",
        "name": "model-catalog-os",
        "tab": "Operating Systems",
        "component": ".plugins-staged/computers/views/OperatingSystemsList.vue"
      }
    ]
  }
}

Used by: ModelCatalogHub, to register plugin tabs. It is the only hub page that does; the others draw their own tabs only.

Reference: ADR-019 Plugin Dynamic Settings Routes


---

### DEPLOYMENT.md
**Add section:** "Air-Gap Deployment Workflow"

```markdown
## Air-Gap Deployment

ShopDB deploys across three air-gapped environments:

Dev PC (the internal git server) <--USB--> Work PC (GitHub) <--USB--> Production VM


### Bundle Creation

```bash
# On work PC
cd C:\Users\<you>\Documents\github\flask-shopdb
./pull-shopdb-bundle.cmd  # Creates tarball for transfer

Deployment to Production

# On production VM
tar -xzf shopdb-deploy-20260911.tar.gz
docker compose exec api flask db upgrade
docker compose exec api flask plugin upgrade-all
docker compose restart api

Automation: /full-deploy skill orchestrates complete workflow (saves 50-100 hrs/year)

Reference: Maintenance-Footprint-Baseline.md (deployment coordination: 312 hrs/year baseline)


---

### CONTRIBUTING.md
**Add section:** "Optimized Pre-Commit Checks"

```markdown
## Pre-Commit Checks

Run before every commit:

```bash
bash scripts/check-naming-and-style.sh
pytest tests/ -x

Performance: Script optimized 2026-09-11 for 5x faster execution:

  • Before: 5-10 seconds (scans all files on disk)
  • After: 1-2 seconds (scans only tracked files via git ls-files)

Override: Set USE_GIT_LS_FILES=0 to use legacy grep-based scanning:

USE_GIT_LS_FILES=0 bash scripts/check-naming-and-style.sh

Enforcement: Violations block CI builds (GitHub Actions)

Commit: 4943e182c3 - Optimize check-naming-and-style.sh


---

### TESTING.md
**Add section:** "Gate Tests"

```markdown
## Gate Tests

Gate tests validate generated documentation and API consistency:

- `tests/test_openapi_spec.py` - OpenAPI spec completeness
- `tests/test_core/test_public_read_surface.py` - public endpoint security
- `tests/test_core/test_authz.py` - authorization decorators
- `tests/test_plugin_migrations.py` - migration chain validation (ADR-008)
- `tests/test_core/test_plugin_settings_hubs.py` - plugin settings hubs (ADR-019)

(Paths corrected 2026-09-18: the first draft put three of these at the top of
`tests/` rather than in `tests/test_core/`.)

**Important:** When you add or modify API endpoints, regenerate docs:

```bash
# Update docs/openapi.json to reflect new endpoints
git add docs/openapi.json

Caveat for the deployment branch (2026-09-18): the parity gate cannot run here. tests/test_api_inventory_parity.py skips itself when docs/api-inventory.json is absent, and that file is not tracked on the deployment branch, so scripts/gen_openapi.py has no input either. docs/openapi.json on this branch is 377 paths at info.version 0.12.0 and documents none of the 24 routes added since 2ac2e6d33. Regenerating it needs the inventory file from the other lineage.

Enforcement: scripts/check-gates-ran.sh verifies gates actually ran (not skipped)

CI failure: "Gate tests FAILED" means docs are stale or missing


---

### SECURITY.md (create if doesn't exist)
**New page content:**

```markdown
# Security Guidelines

## Configuration File Security

**Never commit personal configuration files:**

```bash
# These MUST be in .gitignore
the assistant settings file
the assistant local-settings file
the assistant tool-config file

Why: Personal config files may contain:

  • Plain-text MySQL passwords
  • VM SSH credentials
  • API keys and collector tokens
  • Personal authentication tokens

Incident: 2026-09-11 - Passwords exposed in the assistant tool-config file committed to GitHub

  • Fixed: Removed from git tracking, added to .gitignore
  • Impact: Dev environment credentials only (not production)

Reference: Security-Audit-2026-09-11.md Finding #6

Credential Patterns

Pre-commit hook scans for these patterns:

  • shopdb_pat_* - Collector API keys
  • password = "..." - Hardcoded passwords
  • mysql://user:pass@host - Database URLs with credentials

If blocked: Replace hardcoded credentials with environment variables or config files

How fleet credentials actually work (corrected 2026-09-18)

The paragraph that stood here attributed a decision to ADR-016 that ADR-016 never took. It is replaced with what the code does. Do not reinstate it.

What was wrong. It said ADR-016 delivers credentials by "device tokens" and that credentials must never live in registry keys. ADR-016 says neither. Grepping every ADR for device tokens returns nothing. ADR-016's Decision is a fleet credential store with Fernet at rest, a targeting and precedence resolver, and GET /api/collector/credentials behind a dedicated credentials.fetch scope - and its "Alternatives rejected" section calls registry-only provisioning "a worthwhile FIRST STEP" and "Recommended as tier one regardless". The ban also contradicted shipped code: plugins/computers/client/Report-AssetToShopDB.ps1:367-374 reads the collector key from HKLM:\SOFTWARE\GE\ShopDB, and plugins/endpoints/client/Set-ShopDBServerPins.ps1:4-20 writes the server trust pins to the same key by design. Publishing the old text would have told the next person to delete values the fleet depends on.

What is actually built, as of the deployment branch at 35d4fcd41:

  • Per-PC endpoint credentials. An enrolled PC authenticates with X-Endpoint-Credential (plugins/endpoints/api/agentauth.py). The server stores only a sha256 hash plus a 12-character display prefix (plugins/endpoints/models/credential.py); the secret exists once, in the 201 response to /enroll. On the endpoint it is a DPAPI LocalMachine blob under %ProgramData%\ShopDB\EndpointAgent\credential, in a directory ACL'd to SYSTEM and Administrators only.
  • Bootstrap tokens for the one-line install: hashed at rest, expiry mandatory and bounded to 1-168 hours, uses bounded to 1-500, revocable. The package they serve never carries the collector key.
  • The fleet shared key is still live authority for any PC that is not yet enrolled, and turning it off is a fleet-wide switch, not a per-PC one. The rollout sequence is plugins/endpoints/docs/PER-PC-CREDENTIALS-ROLLOUT.md.
  • ADR-016's own mechanism is NOT built. credentials.fetch, collector/credentials and Fernet return zero hits across shopdb/ and plugins/, matching ADR-016's own "Implementation status, 2026-08-14".

Two things that are genuinely never acceptable, and this part of the original text was right: a credential hardcoded in source, and a credential in git history.

Registry storage is not itself the problem; an unprotected key is. install.ps1 writes the shared collector key to HKLM\SOFTWARE\GE\ShopDB with no ACL (plugins/endpoints/api/siteagent.py:328, helper at :394-411), so it inherits read for BUILTIN\Users and any logged-on user can read it. The repo states that consequence itself at .github/GE-ENFORCE-COLLECTOR-FIX.html:377-380. The rollout plans to clear that value at cutover.

See also: ADR-Conformance-2026-09-18.md, violation 3.


---

## New Page: Automation & Skills
**File:** Create new wiki page  
**Wiki path:** `Operations/Automation-Skills`

```markdown
# Automation Skills

Assistant automation skills created Q3 2026 for common workflows. Save 147-205 hrs/year from 936 hrs baseline.

## Available Skills

### Pre-Commit Validation
**Command:** `/pre-commit`  
**What it does:** Runs pytest, check-naming-and-style.sh, security-scan, migration-check  
**Savings:** 26 hrs/year  
**When to use:** Before every commit

### Docker Rebuild
**Command:** `/docker-rebuild`  
**What it does:** Full Docker rebuild (prebuilt and standard), tests, restarts services  
**Savings:** 26 hrs/year  
**When to use:** After dependency changes (requirements.txt, package.json)

### Agent Deployment
**Command:** `/agent-deploy-full`  
**What it does:** Build C# agent, deploy to VM via SSH, verify service, test heartbeat  
**Savings:** 26 hrs/year  
**When to use:** After agent code changes

### Migration Check
**Command:** `/migration-check`  
**What it does:** Validates plugin migration chains (ADR-008), checks PLUGIN_TABLE_OWNERS order  
**Savings:** 13 hrs/year  
**When to use:** Before adding new migrations

### Production Health
**Command:** `/production-health`  
**What it does:** System health checks (containers, API, DB, disk space, endpoints)  
**Savings:** 52 hrs/year  
**When to use:** Daily monitoring, after deploys

### Security Scan
**Command:** `/security-scan`  
**What it does:** Scans for hardcoded credentials, exposed keys, missing auth, SQL injection  
**Savings:** 13 hrs/year  
**When to use:** Before commits, after security reviews

### VM Snapshot Management
**Command:** `/vm-snapshot create "description"`  
**What it does:** Creates/restores/lists Hyper-V VM snapshots  
**Savings:** 52 hrs/year  
**When to use:** Before risky changes, deploys, testing

### Full Deployment
**Command:** `/full-deploy`  
**What it does:** Complete deployment workflow (validation, bundle, deploy, verification)  
**Savings:** 152 hrs/year  
**When to use:** Production deployments across air gap

### Plugin Scaffolding
**Command:** `/plugin-new "name" "description"`  
**What it does:** Generates complete plugin structure (BasePlugin, models, API, frontend, tests)  
**Savings:** 15 hrs/year  
**When to use:** Starting new plugins

## Total Savings

| Category | Baseline (hrs/yr) | With Skills (hrs/yr) | Savings |
|----------|-------------------|----------------------|---------|
| Pre-commit validation | 52 | 26 | 26 |
| Docker management | 52 | 26 | 26 |
| Agent deployment | 52 | 26 | 26 |
| Migration validation | 26 | 13 | 13 |
| Production monitoring | 104 | 52 | 52 |
| Security scanning | 26 | 13 | 13 |
| VM snapshots | 78 | 26 | 52 |
| Full deployment | 312 | 160 | 152 |
| Plugin scaffolding | 30 | 15 | 15 |
| **TOTAL** | **732** | **357** | **375** |

Note: Realistic savings are 147-205 hrs/year due to task overlap.

**Reference:** Maintenance-Footprint-Baseline.md

Summary

5 new wiki pages drafted:

  1. ADR-019: Plugin Dynamic Settings Routes (architectural decision) - corrected 2026-09-18
  2. Security Audit 2026-09-11 (4 critical + 6 high findings) - refreshed 2026-09-18 against the same branch; every 2026-09-11 finding now carries a verdict with a file and line, and findings 19 and up were added on 2026-09-18
  3. Maintenance Footprint Baseline (936 hrs/year burden, automation opportunities) - annotated 2026-09-18
  4. Architectural Findings 2026-09-11 - rewritten 2026-09-18 with a verdict per finding
  5. ADR Conformance 2026-09-18 (new) - which ADRs hold, which are violated, and the fact that the ADR set is not in this repository

7 existing pages need updates:

  1. PLUGIN-DEVELOPMENT.md (add get_settings_routes() docs)
  2. API-REFERENCE.md (add /api/plugins/settings-routes endpoint)
  3. DEPLOYMENT.md (add air-gap workflow)
  4. CONTRIBUTING.md (add optimized pre-commit checks)
  5. TESTING.md (add gate tests explanation)
  6. SECURITY.md (create new page for credential security) - its ADR-016 section was replaced on 2026-09-18; publish the replacement, not what was there
  7. Automation-Skills.md (create new page for skill catalog)

Total effort to publish: the "~2 hours, copy-paste" estimate no longer holds. Three of the five pages needed correcting against the code before they were fit to publish, and the Security Audit page has not been through that pass yet.


Next Steps

  1. Read the 2026-09-18 notes inside each page before pasting anything. All five pages in this folder have now been checked against the deployment branch at 35d4fcd41.
  2. Copy to GitHub wiki at https://github.com/ge-aero/shopdb-flask/wiki
  3. Update wiki navigation/sidebar to include the new pages
  4. Link related pages. In particular, Security-Audit-2026-09-11.md finding 31 and ADR-Conformance-2026-09-18.md violation 3 are the same ADR-016 misattribution seen from two angles, and the SECURITY.md draft above is the copy that was fixed.
  5. Notify the team

Three corrections that live outside this folder and were therefore NOT made:

  • the assistant-instructions file, lines 3 and 9, say PostgreSQL 15+; docker-compose.yml:20 runs mysql:8.4 and .env.example:29 is a mysql+pymysql:// URL.
  • the assistant-instructions file, line 31 says columns are snake_case; CONTRIBUTING.md:17 says lowercase concatenated with no underscores, and that is what scripts/check-naming-and-style.sh:236 enforces.
  • the assistant-instructions file, line 119 and the assistant quick-reference file, lines 14 and 135 repeat the ADR-016 device-token misattribution.

These wiki pages are based on memory files in the assistant memory directory:

  • security_audit_2026_09_11.md
  • maintenance_footprint_baseline.md
  • architectural_analysis_gortex_2026_09_11.md
  • security_fix_implementation.md
  • workflow_patterns.md
  • repository_structure.md

Memory files are more detailed; wiki pages are summaries for broader audience.