Files
shopdb-flask/docs/adr/README.md
cproudlock b8c22244a1
Some checks failed
CI / backend (push) Failing after 2s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 7s
Multi-site distribution readiness: settings-driven site config, security closeout, release engineering, v0.5.0
Make the app distributable to other GE Aerospace sites (one self-hosted
instance per site, ADR-004). GE values remain the shipped defaults; every
site-specific behavior is now a Setting an admin can change in the UI.

Settings-driven site config:
- Branding: site/QR/badge logos, favicon, primary color (upload endpoints
  mirror the map-blueprint pattern; new Settings > Branding section).
- ServiceNow: search/incident/change URL templates ({ticket}), ticket
  prefixes, enable toggle. Defaults point at the current
  geaerospaceqa.service-now.com global search. Disabled = plain-text tickets.
- Employee-id regex (employeeid_pattern), printer hostname template,
  QR label targets (qr_target_printer / qr_target_usb, blank = asset page,
  else URL template with placeholders), usb_label_style (barcode|qr).
- West Jefferson floor-plan PNGs removed from the tree; generic placeholder
  ships as the map default and sites upload their own blueprint.

Security closeout:
- dashboarddefaults writes now require admin.
- Collector: generic error messages (no str(exc) leak); API key accepted
  via X-API-Key header only (BREAKING: querystring api_key removed).
- IP-based login rate limiting (AUTH_RATELIMIT_* knobs) atop account lockout.
- Setting.set() creation race fixed (IntegrityError retry).

Release engineering and docs:
- __version__ 0.5.0 (distinct from __contract_version__, ADR-007),
  CHANGELOG.md, Gitea Actions CI config, frontend version aligned.
- One wizard-first install story across README/DEPLOY; new CONFIG.md,
  UPGRADE.md, BACKUP-RESTORE.md; CLAUDE.md and ROADMAP de-staled.
- Dockerfile multi-stage build now bundles the frontend; compose binds
  MySQL to 127.0.0.1; stale database/schema.sql and one-off SQL removed.

Debt and fixes:
- .query.get() -> db.session.get() sweep; datetime.utcnow() removed
  (naive-UTC via timezone-aware now); users.py on authz decorators.
- Fixed 4 stale tests (slides feed shape, shopfloor splitperemployee,
  plugin contract purity) and the USB label page field mapping (both usb
  modes emit the cmmc shape: device_id/device_desc).
- Health endpoint reports the real version.

248 tests pass; naming/style check green; frontend builds; fresh-DB
flask db upgrade + seeds verified; QR targets verified by decoding
rendered codes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 15:02:07 -04:00

1.4 KiB

Architecture Decision Records

Each ADR captures a single architectural decision: the context, the decision itself, the consequences, and the alternatives considered. ADRs are immutable once accepted. Superseded ADRs stay in this folder with a pointer to the newer ADR.

Status definitions

  • PROPOSED: drafted, awaiting decision
  • ACCEPTED: decision is in effect
  • SUPERSEDED: replaced by a later ADR (link forward)
  • DEPRECATED: no longer in effect, no replacement

Index

ADR Title Status
001 Asset model is the platform contract ACCEPTED
002 Plugin contract versioning (semver) ACCEPTED
003 Plugin distribution model ACCEPTED
004 Deployment topology (per-site instances) ACCEPTED
005 Equipment vs measuringtools plugin scope ACCEPTED
006 Plugin collector contract pattern ACCEPTED
007 Product versioning and releases ACCEPTED

Authoring

When proposing a new decision, copy the most recent ADR as a template, increment the number, and update this index. Do not edit accepted ADRs in place; supersede them with a new one.