Layout — the reported "skinny scrolling windows"
- .content-area capped the whole suite at 1000px, so on a 1920 screen the embedded
Work Package Creator ran in a ~930px column with its own scrollbar inside the
page's. The wizard now caps at 1700px and the Creator/Dashboard tab goes
full-bleed: the iframe fills the window below the app chrome and owns the only
scrollbar. Needed `flex: none` on the content area — as a `flex: 1` item its
flex-basis overrode `height`, leaving the used height indefinite so the child's
`height: 100%` collapsed the iframe to its 150px default.
- The SOP wizard's fields were one per row; they now flow into ~340px columns.
Navigator — now an auto-hiding drawer
- It was a fixed 262px column that stole width from the form AND was hidden below
1100px, so embedded (the normal path) it never appeared at all — that's the
"broken side menu". It's now an overlay drawer behind a slim always-visible edge
handle: hover or tap to open, move away / Escape / pick a package to close, or pin
it to keep it open (pinned shifts the form and the page chrome across, and is
remembered). A gutter keeps the handle off the section-nav chips.
Bugs found while checking the site over
- collectStepData() still read the SOP team fields as text inputs, but wave 1 made
them account pickers — so it wrote a user ID into state.team.pm where the display
NAME belongs, and the SOP would print `user_ab12…` as the PM. Now synced properly
from the pickers.
- loadSampleData() set .value on those selects with fictional names; setting an
unmatched value on a <select> silently does nothing, so the sample lost its team.
It now stores them as names without an account, which the picker shows as
"(no account)".
- My earlier CSS block replacement had deleted the SOP-chip, people-picker and
critical-tag styles. Restored.
Same picker everywhere the SOP names someone
- Sign-off roles (step 3, required and optional) are account pickers now, storing
userId alongside the name, so a signature belongs to an account that can be
notified. Titles stay free text.
Per-project permissions (asked for: "change project permissions for individual users")
- project_members.role overrides the account's role on that project, so a PM on one
job can be a Project User on another. Empty = inherit; app admin is admin
everywhere. effective_role() feeds require_project_admin, so WP delete, completed-
SOP edits and project delete are all judged per project.
- Project access is now its own column in the admin console (it was buried among the
action buttons, which is why it couldn't be found), showing the project count per
account; the dialog sets access plus the role on each project.
- The members endpoint reports each person's effective role on that project.
Verified: 157 API checks across five suites on clean databases (44 permissions +
22 password reset + 34 search/localization + 39 gates/notifications + 18 new
per-project permission checks), 16 drawer-behaviour + 4 pinned-mode UI checks driven
in headless Chrome, and probes confirming the team/sign-off pickers populate and no
longer corrupt state.team on step navigation. Screenshots reviewed at 1920x1080.
Service-worker cache bumped to v3 so browsers pick up the new shell.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Site comments (8/3)
- BIM card: LOD removed, IFF # added next to the coordination status, and required
once that status is "Signed off (IFF)" — an unnumbered sign-off isn't traceable.
A LOD already stored on a package is preserved and shown as legacy, not blanked.
- The blue "from SOP types" subtext under a field is now a SOP chip on the label
with the detail in a tooltip. The chip stays visible rather than hover-only:
field tablets have no hover, and "this came from the SOP" is the part that
matters. The hint elements stay in the DOM (hidden) so the code writing to them
keeps working; an observer mirrors their text into the tooltip.
- Specification Section is no longer typed per package. Each WP type carries a
spec section on the SOP; the field is read-only in the Creator and follows the
type, with the SOP's spec folder linked underneath. This reads both spec
comments as one intent — stop typing it, derive it.
- Assignees and Distribution are multi-selects over the SOP project team, showing
each person's job function, with the CM pre-added to Distribution (removable per
package) and a free-text option for people with no account. The stored display
strings are unchanged so print/export/dashboard keep working; account ids ride
alongside for the notification work in wave 3.
Localization + time
- Per-user locale/timezone (Language & time in the user menu), an app-wide default
in the admin console, then the browser. Timezones are validated against the
server's zoneinfo and the picker is fed from it. Calendar dates are formatted
from their parts so a due date never reads a day early in another zone.
- Every displayed timestamp now goes through the shared helpers.
Top-bar chrome
- Project switcher beside the logo and a centered global search, injected into
either generation of top bar; skipped in an iframe so the embedded Creator
doesn't get a second one. Ctrl/Cmd-K focuses search.
- GET /api/search covers work packages, projects and SOPs, scoped to the caller's
projects, hiding archived packages, with LIKE wildcards escaped.
Fixed along the way: showForm() cleared every card's inline display, which undid
applyKind() — so the Package Type and BIM cards reappeared on an install-only
project. Split out applyKindVisibility() and re-apply it there.
Verified: 100 API checks on a fresh database (44 permissions + 22 password reset +
34 search/localization), 24 driven UI checks against the real Creator page in
headless Chrome (SOP chips, both people pickers, spec auto-fill, critical tags,
BIM suppression), and the chrome harness on both bar styles. Screenshots reviewed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Acts on the site comments from 8/3 plus the follow-ups. Foundation work first —
four of the comments all needed the project team to resolve to real user accounts.
Permissions vs project role (new)
- User.role is now the PERMISSIONS role: admin | project_admin | project_user.
project_admin may delete work packages, change a SOP after it is complete, and
delete a project; project_user may not (archiving a WP is still open to them).
Enforced by require_project_admin() server-side; the UI only hides dead ends.
- New User.project_role holds the person's JOB FUNCTION on the project. It grants
nothing — it feeds the SOP team pickers and notification routing.
- Admin console shows both columns and explains the difference. Migration rewrites
the legacy role 'user' to 'project_user'.
- Deleting a project was previously open to any member and unaudited; it now needs
project_admin and writes an audit event. ProjectData.remove no longer drops the
project from the local cache when the server refuses.
SOP project team from user accounts
- PM/APM/CM/QM and additional team members are pickers over the project's members,
storing the account id next to the display name. A name from an older SOP with no
matching account is kept and flagged rather than dropped.
- The WP Creator lists the SOP team first in the Owner picker, and a new package
defaults to whoever is creating it.
Critical constraints
- SOP constraints carry a Critical flag; buildConstraints() now copies the whole
definition through to the package (it previously reduced them to names, losing
description too), and critical rows are marked in the WP form. The email on
reopen-after-release is wave 3.
Password reset by email
- login.html gains Forgot password and a set-a-new-password view, offered only when
the server reports email is actually configured.
- Single-use signed token (AUTH_RESET_MINUTES, default 60) bound to token_version,
sent immediately rather than through the notifications outbox so a reset link is
never persisted. Identical response for unknown accounts; per-account send
cooldown; a completed reset clears any login lockout.
- Session and reset tokens are no longer interchangeable.
BIM kill-switch
- New admin Features card with bim_enabled, OFF by default. The SOP creator hides
the BIM section and the Creator treats every package as install-only while it is
off; a SOP that already has BIM keeps its data untouched.
Verified with two throwaway-database test scripts: 44 checks on the permissions
matrix and token handling, 22 on the reset flow end-to-end against a local SMTP
sink (real message captured, link extracted and used). Front-end files parse-checked
in headless Chrome. Not yet exercised in a browser against a real login.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Brings the Work Package Suite from a browser-local prototype to a
multi-tenant, SQL-backed deployment hardened for customer IP.
Auth & access control
- Local username/password login (bcrypt + JWT in an HttpOnly cookie),
admin-managed users, per-project membership, and project-scoped API access.
- Admin console: change user roles, view the audit trail, manage settings.
Security hardening
- CSP / HSTS / X-Frame-Options / nosniff headers in nginx; Secure cookie via
X-Forwarded-Proto; CSRF Origin check; attribute-safe output escaping.
- Login lockout, token_version session revocation, stronger password policy,
fail-closed secret loading, encrypted (AES-256) database backups.
Persistence & schema
- SOPs and Work Packages are now DB-backed and shared across users, written
through a durable client sync outbox that queues offline edits.
- Alembic migrations applied automatically on container start.
New capabilities
- Phase 2 dashboard (progress, gating, pagination, archive).
- Phase 3 PWA "Field View" with offline caching and auth fallback.
- WP owner assignment with OPTIONAL email notifications, OFF by default and
toggled from the admin console. SMTP password is read only from the
SMTP_PASSWORD env var (never stored); emails carry a WP number + deep link,
never customer IP.
Also: IBM Carbon restyle, Help section, and DEPLOYMENT.md brought up to date.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
That deliverable is a BIM/EWP output (and on install-only jobs Prime
often doesn't own it), so it no longer appears in the default IWP
sequence. It now lives in the BIM sequence as the hand-off step, so it
only shows on BIM-enabled projects.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reintegrates C-West8's "storing data in DB instead of client only"
(commit e5102446 on shared-data) on top of the BIM / per-package work.
localStorage becomes a per-browser cache; the server is authoritative.
- project-data.js: pullProject() hydrates the apps' existing localStorage
keys from the API on load; pushSOP()/pushWP()/removeWP() write through
on save/delete. WPs store the whole flat object in `data`, so BIM
fields, kind, and projectLinks round-trip intact.
- index.html: home pulls the project before showing SOP status; feedback
loads from /api/comments (server-authoritative, local fallback).
- work-package-suite-app.js: pull-then-restore on boot; completeSOP
pushes the SOP to the server.
- wp-creation-app.js: save/duplicate/issue/setStatus push; delete/clear
remove; boot pulls from the server first, then boots off the cache.
- server/app.py: /api/sops and /api/wps take full=true to return the
data JSON for one-request hydration (list stays lean by default).
Co-Authored-By: C-West8 <125926137+C-West8@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- enableBIM() prepends the BIM steps (BIM precedes construction) instead
of appending them.
- Default construction sequence updated to the agreed flow (2D sheets /
spool drawings -> conduit -> tray -> QC hold -> wire pull -> device ->
termination -> QC hold -> commissioning -> as-built), with QC-hold gates.
- Sample project now enables BIM/VDC so it demonstrates the full
BIM -> construction sequence.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the whole-project BIM 'mode' with an opt-in capability + a
per-package kind, so a single project can produce both model and
install packages (and install-only projects are unaffected).
SOP tool:
- Step 4 "Include BIM / VDC work packages" checkbox (state.bimEnabled).
Enabling adds BIM package types + BIM release gates (flagged bim) plus
BIM roles/sources/process steps alongside the construction defaults;
disabling strips the bim-flagged items.
- Generated SOP carries bimEnabled and a per-type / per-constraint bim flag.
- Required sign-off role titles stay editable (no longer force-renamed).
Work Package Creator:
- Shows a Package Type selector (Install IWP / BIM EWP) only when the
SOP has bimEnabled; kind is saved per package and labeled in the output.
- WP types and release gates are filtered by kind (BIM types+gates for
EWP, install types+gates for IWP).
- EWP reveals the BIM Details card and hides controls.dev Assets /
Materials / Kitting-MIMO; IWP shows those plus the "Enabled by - BIM
package" traceability link.
Supersedes the earlier whole-project BIM mode.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SOP tool:
- "Load BIM / VDC template" (Step 4): one click sets BIM deliverable
types, install-phase disciplines, BIM release-gate constraints (with
EN06 citations), the BIM process sequence, reference sources, BIM
sign-off roles, and MWP##-[Area]-[PHASE] numbering. Tags the SOP mode
as 'bim'.
- Step 3 required sign-off role titles are now editable (default
Superintendent/Foreman); the BIM template sets them to BIM Coordinator
and Construction Lead (CRS).
- Step 7: capture a project-homepage link for the chosen tracking and
commissioning platforms.
Work Package Creator:
- BIM mode (SOP.mode==='bim'): hides controls.dev Assets, Material List,
and Kitting/MIMO; shows a BIM Details card (LOD, model area, clash /
coordination status, linked scan).
- Project tracking/commissioning links are copied onto every WP and
shown in the WP output.
- "Enabled by - BIM package(s)" field links a field IWP back to the BIM
package that enabled it (EWP -> IWP traceability).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Access control:
- project_members table; non-admins only see/operate on assigned
projects (enforced across projects, SOPs, work packages — 403 else),
admins bypass. Creating a project auto-grants its creator access.
- Admin API to get/set a user's project assignments, plus a checkbox
assignment dialog in the Admin Console user list.
UI / workflow:
- Login page: drop the "Prime Controls" wordmark next to the logo.
- SOP tool: remove emoji icons from buttons and nav tabs.
- Rename "Step Comments" to "Feedback"; the author auto-populates
(read-only) from the signed-in user.
- Move usage-log viewing to the Admin Console; add an admin card that
lists all feedback/comments (who, what, page + step, when).
- Sample project name -> "Micron FMCS Install (sample)".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- API smoke test (server/smoketest.py): stdlib end-to-end check of health,
projects, SOPs, WPs, the AWP issue gate (409 → 200), status, metrics,
comments, and cascade delete. Referenced from DEPLOYMENT.md.
SOP config:
- Constraints: fix custom constraints never appearing — renderStandardConstraints
no longer clobbers state.constraints; customs render in their own list with
remove buttons; modal gains a free-text "Add" field.
- Sources: add column headers (Data Type / Location-Platform / URL / Notes);
preset data types are now fixed labels, "Add Source" creates an editable
custom row.
- Issuance strategy: add a tooltip + worked examples for each option.
- Remove the "Comment submitted" acknowledgement popup (home + suite); keep the
commenter name between comments.
WP creator:
- Clearing the last open constraint now offers to mark the package Issued and
scrolls to the status control.
- Form sections are collapsible (click a section heading to fold it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Cost codes: drop everything after 4990 (material/quality/admin codes removed).
- WP creator: add "Duplicate" (asks how many copies; each a clean Draft with
unique number/subject, approvals & closeout cleared). When embedded the WP
toolbar now shows only New + Duplicate.
- Condense duplicated toolbars: the embedded creator's Usage Data, Load Example/
Sample SOP, Comments, View SOP and Dashboard buttons are hidden; the suite's
top-right "Usage Logs" and "Load Sample" are the single instances.
- Load Sample is context-aware: SOP tab loads the sample SOP, WP/Dashboard tab
loads the example Work Package in the creator.
- Dashboard moved to a nav-tab next to SOP Configuration / Work Package Creation.
- Remove "Prime Controls" branding from the embedded WP menu.
- Remove "Bill Clarida" from the example WP distribution and the step-comments
name placeholder.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- SOP Complete now returns to the project home page after the confirmation
popup (instead of staying on the SOP tab), and stamps projectId onto the SOP.
- WP creator no longer substitutes the Micron SAMPLE_SOP when a project is
active but its SOP isn't found — it shows a "complete the SOP first" empty
state instead. Sample is only used for a standalone (no-project) preview.
This was the source of "loaded with sample data I didn't select."
- SOP WP Types step gains "+ Add Custom Type" (editable name + remove);
blank-named custom types are dropped from the generated SOP. Custom types
round-trip via the saved state.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the free-text "Typical WP Size" with a preset dropdown (Small /
Standard / Large / Custom). Choosing a preset auto-fills the max-hours split
threshold (still editable). The chosen band is now surfaced next to Est. Hrs
in the creator's size hint (not just the View-SOP modal), alongside the
threshold/over-threshold warning. Sample SOP aligned to Standard (80 hrs).
repopulateForm preserves a non-preset saved value as a dropdown option.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SOP and Work Package localStorage keys are now namespaced by the active
project via ProjectData.key(base) -> base+'__'+<projectId> (SK() in the
suite, wpKey() in the creator), so switching projects shows that project's
own SOP and packages. project-data.js runs a one-time discard of the legacy
un-namespaced keys (guarded by wp_ns_migrated_v1), per the chosen approach.
Active project is resolved before the store loads in both the suite and the
creator so namespaced keys resolve correctly, including standalone deep-links.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Projects become the top-level container; SOPs and Work Packages belong to one.
Backend:
- New projects table + CRUD (/api/projects).
- sops.project_id (FK, cascade) and work_packages.project_id added;
list/latest/metrics endpoints accept a project_id filter.
Front end (now under html/):
- project-data.js: shared API-first ProjectData adapter with localStorage
fallback + active-project helpers.
- Home page: removed "About This Suite"; added a Project picker (create /
use sample / select). Tool cards stay hidden until a project is active and
carry &project=<id>; hero shows the active project.
- Suite reads ?project, resolves it, shows it in the header, and prefills the
SOP project fields; passes &project into the WP-creator iframe.
- WP creator stamps projectId onto saved packages.
SOP/WP localStorage is not yet namespaced per project (next step).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>