Commit Graph

25 Commits

Author SHA1 Message Date
benjamin.baker
d6bd7b5f54 Fix endpoint user-context collection running in the wrong session
Mapped drives reported Unavailable on endpoints where the operator could
see them fine. The data path was intact; the collection was running under
the wrong token. Mapped drives are per logon token, so an elevated probe
enumerates a different drive table than the interactive user.

Collection:
- Pin the user-context spool path so the probe and service agree on one
  location, and persist/overwrite it instead of deleting on read.
- Refuse to collect while elevated (exit code 2) rather than emitting a
  confident wrong answer, and stamp elevated/username on the spool.
- Reject spools stamped elevated or from an unexpected account on read,
  so an admin run cannot masquerade as valid.
- Log netuse/smbmapping/userlistener counts so each run leaves evidence
  of what it actually saw.

Install and launch context:
- Move collection to a 'ShopDB user-context probe' scheduled task under
  S-1-5-32-545 at RunLevel Limited, the only mechanism that reliably runs
  in the operator's own session. Verify registration and record it in the
  install ledger.
- Stop starting the tray as a child of the elevated installer; explorer.exe
  de-elevates without changing ACCOUNT, so an admin install produced an
  admin tray. The Run key only fires at logon, which left the tray dead on
  a machine already signed in, so add a transient 'ShopDB tray first launch'
  task that starts it once in the existing session and unregisters itself.
- Hide the console window during --collect-usercontext. The agent is a
  console exe; the tray used to mask this with CreateNoWindow, but the
  scheduled task invokes it directly and flashed a window every cycle.

Installer edits are in _install_script() in plugins/endpoints/api/siteagent.py,
which generates the install.ps1 that actually ships. The standalone
agent/installer/install-shopdbagent.ps1 was never shipped once the package
moved to the UI builder and is deleted here to stop the divergence that
caused an earlier fix to land in a file no endpoint ever ran.

Versions: agent 1.10.1, tray 1.3.0. These share the pinned spool path and
must be deployed together.

Pre-existing test failures unrelated to this work (8, identical on a clean
tree): docs publishable/versions, plugin contract symlink scan, import
guard tamper check, security headers upload sandbox, and three endpoint
timestamp tests.
2026-09-05 17:32:03 -04:00
benjamin.baker
ba38e4d39d PC Detail: flow Details cards, drop the IP Configuration card
Details tab card layout
-----------------------
The Details tab sat on .content-grid, a two-column CSS grid. Grid packs
items into implicit rows, so every row is as tall as its tallest card and
align-items:start leaves the shorter one with dead space beneath it:
Warranty is short, Endpoint Status is tall, and Policy had to wait for the
taller of the two rather than sliding up. That read as a staggered layout.

Switched that one tab to multicol via a .details-flow modifier, which has no
rows at all - each card starts where the previous one ended, so the holes
close while cards still size to their content.

Multicol is deliberately NOT applied to .content-grid globally. The note by
that rule in style.css records why it was abandoned there: a column-span:all
child (.pap-span, used by table panels) overlaps the shorter column when the
two are unequal. That cannot happen on this tab - every panel in the details
group is a keyvalue or list render, and spansFullWidth() only returns true
for table (or a tabs panel holding one), so nothing in the subtree spans.
Monitors and Service/Process DO carry table panels and stay on grid.

The modifier is scoped to PCDetail, so the nine other detail views on
.content-grid are untouched.

Chosen over JS masonry on purpose. Masonry packs perfectly but has to
measure every card and re-measure on resize, on panel collapse and on every
async panel load - and these panels fetch after paint, so it would mean
continuous forced reflow on a page that already polls. This is pure CSS:
no measurement, no observer, no runtime cost. The tradeoff accepted is that
column bottoms can end at slightly different heights.

Cards carry break-inside: avoid so none fragments across the column break,
and the 25px spacing returns as a margin because multicol has no gap between
stacked items the way grid does.

IP Configuration card
---------------------
Removed: the data has no purpose on the page anymore. Taken out at the root
rather than hidden - the panel declaration, the /asset/<id>/ipconfig route
and the _IPCONFIG_COLUMNS constant all go, since a route with no consumer is
dead surface that still answers requests.

test_the_two_cards_do_not_duplicate_columns_beyond_the_address existed only
to police the history/config column split; with one card gone it guards
nothing, so it and its import go with it. The panel-count assertion in
test_endpoints_asset_panels_are_computer_scoped moves 15 -> 14, which is the
test doing its job and catching the removal.

IP History is unchanged and still carries the address list.

Not addressed here: three tzset() tests in test_endpoints_plugin.py fail on
Windows because time.tzset() is Unix-only. Verified pre-existing against
unmodified code; they pass in the Linux container.
2026-09-05 15:27:50 -04:00
benjamin.baker
86985efcf2 Fix user-context collection, split agent log destinations, widen upload cap
Mapped drives stopped reporting because the user-context path failed silently
in three separate places, and none of them left a trace to read back.

- Probe: launch via -EncodedCommand instead of staging a temp .ps1 and running
  powershell.exe -File. A missing or quarantined script file fails BEFORE any
  statement runs, so the script's own try/catch never sees it and the only
  symptom is exit -196608.
- Spool: pin to the ShopFloor profile. Resolving it through WTSQueryUserToken
  is privileged, endpoint protection blocks it, and on failure the tray
  (writer) and service (reader) silently disagree about the path.
- Spool: consume after a successful parse, so a stopped tray cannot keep
  re-reporting stale mapped drives as current. Unparseable files are left in
  place for the next cycle.
- Logging: user-session components cannot write to Program Files or to the
  SYSTEM-owned ProgramData log directory, and the file sink degrades to a
  silent no-op when it cannot create its directory. Tray and probe now log to
  C:\Users\ShopFloor\ShopDB\Logs, installs transcript to ProgramData, and the
  sink records a SinkProblem instead of swallowing UnauthorizedAccessException.
- Installer: provision the operator spool/log directories with ShopFloor:Modify
  before the tray first runs, and stop the transcript via trap so a throw
  cannot orphan exactly the failed install worth reading.
- Upload cap 64 -> 128 MB: the self-contained tray publishes at ~69 MB and was
  rejected on SIZE, but the size check returns before the PE is parsed, so the
  operator only ever saw a version-detection failure.

AGENT-CONTRACT.md gains a normative section defining the three security
contexts, their log destinations, the fixed spool path and consume-on-read.

Agent 1.8.0 -> 1.8.1, tray 1.1.0 -> 1.1.1 so the deployed build is
identifiable from a log line.
2026-09-05 14:20:07 -04:00
b0bd73f62d Import the wilm agent store, WINC adoption work and batches CLI, with four fixes 2026-09-03 08:16:38 -04:00
bb733f1332 Merge the wilm work, act on the five-agent review, verify the launch-path policy on Windows 2026-09-02 16:15:53 -04:00
2144305433 Add the Darkwing vulnerability scan workflows 2026-09-02 12:17:46 -04:00
80bb7b5ba1 Merge wilm: endpoints plugin, agent, policies, CSV import, Entra fields
Thirteen commits from benjamin.baker plus the review fixes. Everything he built
is here: the endpoints plugin and its command queue, the .NET endpoint agent,
the computers policies subsystem, the site-asset CSV import with its adapters
and collector, Entra device identity, and the catalog hand-merge.

His branch predates four commits on main (section ticking, the generator share
links, Secure Send copy message, and the smoke-test workflow), so those come
through untouched - nothing of ours is removed by this merge.

wilm stays as its own branch; this does not close it.
2026-08-28 15:56:58 -04:00
2de9c005e8 Merge the smoke-test commits made directly on GitHub
Two commits were made in the GitHub web editor to test whether the self-hosted
runner group was shared with this repository - it is. They branched from
e60945e, while the publication export produced its own two commits from the same
parent, so main here and main on GitHub had diverged and the ff-only push was
correctly refused.

Merging rather than force-pushing: the commits are real history somebody made,
and the wilm branch has already merged them, so discarding them from main would
only delay their return.
2026-08-28 15:33:24 -04:00
a775b87db7 gate guard, runtime spec, Node 24 actions 2026-08-28 15:28:07 -04:00
Proudlock, Cameron1 (GE Aerospace, US)
fa8beca1e2 Fix formatting in smoke.yml workflow file 2026-08-28 15:16:49 -04:00
Proudlock, Cameron1 (GE Aerospace, US)
c0435e7ed1 Add smoke test workflow for runner validation 2026-08-28 15:14:56 -04:00
benjamin.baker
af133372b4 Gate endpoint UI refresh on fresh telemetry and land endpoint agent
A command reaching 'succeeded' only proves the agent ran the action, not that it posted a new telemetry snapshot. Reloading panels on command success alone re-rendered stale service/process rows, so a stopped process could still show running right after Refresh Status.

Add a lightweight telemetrymeta probe exposing lastreportedat and gate both the header Refresh Status action and inline row Start/Stop on that stamp advancing past a pre-action baseline. Polling is bounded so an offline or idle agent never hangs the button, and messaging distinguishes a confirmed refresh from a queued one.

Bring the .NET endpoint agent source (service, tray, installer) into the repo so Cameron can merge and test, with an agent/.gitignore keeping bin/obj/publish out. Includes the DncMain launch-path fix, tray single-file host env scrub, and best-effort file logger.
2026-08-28 15:07:20 -04:00
98badcbc26 publish the runtime spec; gate guard 2026-08-28 14:04:10 -04:00
benjamin.baker
01734e5449 harden CSV import reconciliation and preserve saved model selections
Default fuzzy reconcile threshold to 0 and refuse merges when digit runs differ so numbered labels like Bay 311 never bind to Bay 310. Keep edit forms from clearing saved model fields when category filtering hides untyped rows. Includes in-progress computers policy and endpoints command feature work.
2026-08-28 09:29:09 -04:00
3d43cb3d86 Windows installer: payload hash-locking, SBOM, client-IP handling, operator docs 2026-08-03 15:08:20 -04:00
ffe9fa1cce CI: drop rsync dep in build-site.sh; move MySQL migration job to internal CI (ARC has no service containers) 2026-07-20 09:01:59 -04:00
5e33189cd9 CI: run on self-hosted arc-runner-set (org IP allow list blocks GitHub-hosted runners) 2026-07-20 08:45:13 -04:00
da28ee9f33 Lean build: always ship core (manifest-less) frontends 2026-07-19 12:10:45 -04:00
99025d10f0 ADR-013 Phase 5: lean per-site builds (build-site.sh + guards + CI) 2026-07-19 00:11:41 -04:00
61514b61a8 Add Copilot custom instructions 2026-07-17 20:56:53 -04:00
199438cec9 Add flask seed demo sample data; widen settings.description to TEXT 2026-07-17 20:32:38 -04:00
f255de4097 Add cryptography dependency for MySQL 8 auth 2026-07-17 19:41:43 -04:00
cfa3d1da36 Standardize on Python 3.13 (matches prod 3.13.7) 2026-07-17 19:30:20 -04:00
2afb3027dd Docs audit fixes: kiosk code drift, PowerShell chains, links, leaks, CI auth 2026-07-17 18:06:02 -04:00
9757de50b1 Add GitHub Actions CI + Windows notes on developer docs; neutralize internal-host references 2026-07-17 15:13:35 -04:00