Commit graph

3 commits

Author SHA1 Message Date
emirhanmamak-blueforce
5cc312f58a Unify Blueforce identity and Python operator surfaces 2026-09-17 13:22:26 +03:00
emirhanmamak-blueforce
e28783e563 feat(offline-repo): build the APT index so installs work without network
The package pool was committed but the installer still stopped at "no local
package repository": it requires the compiled bundle (Packages, Packages.gz,
packages.lock.tsv, SHA256SUMS), and building that had never run.

The bundle
- 1321 packages, 884 MiB, Ubuntu 26.04 amd64, built with apt-ftparchive on the
  fleet's own release so the closure matches the devices.
- built/pool/ is gitignored: those .deb files are already tracked once under
  provisioning/offline-repo/packages/, and the same ~890 MB does not need a
  second path. What the installer reads from the bundle is the index.
- The output directory is chmod 0755: mktemp -d created it 0700 and left it
  so, which made a valid bundle unreadable to the installer's probe.

dpkg-deb output was parsed wrong in four places
- `dpkg-deb -f <file> Package Version` prints "<Field>: <value>", and the
  callers kept the whole line, so the value carried its label. build-index.sh
  therefore accepted no package at all and reported an empty pool;
  add-packages.sh rejected every real .deb as an invalid name, missed version
  conflicts, and copied a duplicate; build-offline-repo.sh never matched a pin.
- The test suite could not see any of this: its dpkg-deb stub emitted bare
  values. The stub now prints the labels exactly as the real tool does, which
  is what surfaced the remaining three sites.

Tests
- The secret scan covers the files we author, not apt-ftparchive's index over
  third-party packages: polkit's own description reads "...asked for their
  password:", which is prose in the packages, not a leak. Any secret reaching a
  manifest, README or tool is still caught.
- The "test build must not touch the bundle" assertion now compares the
  directory before and after instead of demanding it be empty, so a
  maintainer's real build is not reported as test spill.
2026-09-16 21:42:27 +03:00
emirhanmamak-blueforce
1387186b03 feat(bfos): Python operator console, Turkish UI, committable offline packages
Switches the operator path from bash-only to a Python console, keeps the bash
menu as a fallback, and makes the offline package set travel with the repository
so the person installing a device never downloads anything.

bfos/ (stdlib only, no textual/rich: those would need a download, which defeats
the offline goal):
- simple mode offers three choices (Kur / Durum / Çıkış); the detailed mode with
  all 21 fleet operations and the local installer is reachable from the menu or
  with --full, so a first-time operator is not buried in options
- gate parity with the bash console: scope read from the playbook file and
  refused on mismatch, production needs a typed token plus a separate approval,
  release-gated runs need their wave name typed, destructive runs need a second
  approval, "all" walks wave by wave and stops at the first failure
- Turkish throughout; audit log at /var/log/blueforce-console.log (600, falls
  back to the user state dir) with a single redaction choke point
- bfos/ui_gui.py adds an optional tkinter window over the same operations layer;
  headless and missing-tkinter cases explain themselves in Turkish

admin/bf-bootstrap.sh: links the Python console as `bf` (primary) and keeps
`bf-menu` (fallback), reports both, and recommends `sudo bf`.

Offline packages are committable now (this was the blocking contradiction):
- .gitignore ignored `Packages`, `Packages.gz` and `packages.lock.tsv` everywhere,
  so a built bundle could never be committed and the installer would always have
  been told to download. provisioning/offline-repo/built/ is now allowed through
  while scratch output stays untracked
- provisioning/offline-repo/{add-packages.sh,build-index.sh,repo-manifest.yaml}
  plus a Turkish step-by-step README for the repository owner
- the over-broad `*token*` ignore rule is narrowed to `*[-_.]token*` so ordinary
  filenames are not silently excluded while token files still are

Tests: run-all.sh now runs the Python suites too (previously it collected only
*.sh, so 212 Python assertions were silently skipped) and executes from the repo
root. 11/11 pass, exit 0.

Two test expectations were corrected rather than the code: a read-only
wave-scoped report legitimately asks for no gate token (the bash console never
did either), so that assertion now checks the command carries operation_wave and
operation_confirmed, and a new test asserts release-gated runs still require
their token. The bootstrap completion contract moved from `sudo bf-menu` to
`sudo bf`.
2026-09-16 16:15:27 +03:00