Files
shopdb-flask/tests/test_plugins/test_geenforce_parity.py
cproudlock d85b33bd68
All checks were successful
CI / backend (push) Successful in 1m36s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 8s
Build GE-Enforce manifest-store plugin (P0/P1): model, importer, parity gate
First execution phases of docs/proposals/ge-enforce-plugin.md. The GE-Enforce
manifest becomes shopdb data.

P0 scaffold: new geenforce plugin (api_prefix /api/geenforce, default_enabled
false, core_version >=0.7.0). Registered in PLUGIN_TABLE_OWNERS (ADR-008); its
0001 baseline really creates the tables.

P1a model: one wide manifestentries table + entrytype discriminator (not STI,
not JSON blob), manifestscopes (UNIQUE scopename+phase), the three multi-value
filter child tables, inusechecks + processes, immutable manifestpublishedversions
(frozen rendered JSON), manifestpayloads (inline, capped), pctypealiases
(mirror of the engine lib's alias graph). regvalue stored as its raw JSON
literal so DWord typing survives.

P1c importer + exporter: parse common + gea-shopfloor-* + preinstall.json into
draft rows and rebuild the JSON verbatim from rows in sortorder.

P1d parity harness (GATE A): filters.py mirrors the engine's four filter
functions + alias graph; parity.py proves import+export is behaviorally lossless
(field-identical + same-entries-fire across 18 machine-profile fixtures) WITHOUT
byte-diffing. Verified PASS against all 11 real reference manifests (64 entries)
and a synthetic site-neutral fixture covering every type/filter (the CI gate).

First slice (gea-shopfloor-cmm shape): service layer (import/publish/rollback/
export-to-share), CLI (parity, import-share, publish, export-share), and the
client endpoint GET /api/geenforce/manifest serving the current published
snapshot (never the draft) with ETag/304. Split permissions
geenforce.manage/publish/fetch. Tests prove import->publish->serve, draft edits
never change served bytes, publish+rollback, and auth (401 unauth/wrong-scope).

Contract 0.11.0: added service_token_authorized(scope) to shopdb.api so plugin
service endpoints authorize a scoped managed token without importing core token
internals. Documented in PLUGIN-HOOKS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 16:53:18 -04:00

143 lines
6.0 KiB
Python

"""GE-Enforce P1 parity gate (Gate A): import + export is behaviorally lossless.
Runs the DB-free parity harness (parse -> in-memory rows -> render -> compare)
over a synthetic, site-neutral manifest that exercises every entry type,
detection method, targeting filter, RegValue typing, InUseCheck, and preinstall
flag. The synthetic fixture is what CI gates on (no real site data is vendored
into the framework repo). If the real GE-Enforce reference share is present
(dev), it is also checked.
"""
import os
import pytest
from plugins.geenforce.parity import run_parity, load_fixtures
from plugins.geenforce.importer import discover_share, load_manifest_file
# A site-neutral manifest covering the whole schema surface.
SYNTHETIC = {
'Version': '2.6',
'_comment': 'Synthetic parity fixture (not a real site manifest).',
'Applications': [
{
'_comment': 'MSI with Registry detection, version gate, InUseCheck.',
'Name': 'Sample MSI', 'Type': 'MSI',
'Installer': 'apps/sample.msi',
'InstallArgs': '/qn /norestart ALLUSERS=1',
'_CmmVersion': '2019',
'DetectionMethod': 'Registry',
'DetectionPath': 'HKLM:\\SOFTWARE\\Sample',
'DetectionName': 'DisplayVersion', 'DetectionValue': '1.2.3.4',
'InUseCheck': {
'Behavior': 'CloseAndReopen',
'Processes': [
{'Name': 'sample', 'ExePath': 'C:\\sample.exe',
'GracefulCloseTimeoutSec': 15},
{'Name': 'other'},
],
},
},
{
'Name': 'Sample EXE', 'Type': 'EXE', 'Installer': 'apps/sample.exe',
'InstallArgs': '/quiet', 'WaitTimeoutSec': 60,
'DetectionMethod': 'FileVersion',
'DetectionPath': 'C:\\sample.exe', 'DetectionValue': '1.0.0.0',
},
{
'Name': 'Sample PS1', 'Type': 'PS1', 'Script': 'scripts/run.ps1',
'Args': '-Force', 'DetectionMethod': 'Always',
},
{
'Name': 'Sample File', 'Type': 'File', 'Source': 'configs/app.json',
'Destination': 'C:\\ProgramData\\app.json',
'DetectionMethod': 'Hash', 'DetectionPath': 'C:\\ProgramData\\app.json',
'DetectionValue': 'a' * 64,
'PCTypes': ['gea-shopfloor-collections', 'gea-shopfloor-cmm'],
},
{
'Name': 'Sample Registry DWord', 'Type': 'Registry',
'RegPath': 'HKLM:\\SOFTWARE\\Sample', 'RegName': 'Enabled',
'RegValue': 1, 'RegType': 'DWord',
'DetectionMethod': 'ValueMatches',
'DetectionPath': 'HKLM:\\SOFTWARE\\Sample', 'DetectionName': 'Enabled',
},
{
'Name': 'Sample Registry String', 'Type': 'Registry',
'RegPath': 'HKLM:\\SOFTWARE\\Sample', 'RegName': 'Mode',
'RegValue': 'on', 'RegType': 'String',
},
{
'Name': 'Sample INF', 'Type': 'INF', 'Installer': 'configs/driver.inf',
'DetectionMethod': 'pnputil', 'DetectionPattern': 'SampleDriver',
},
{
'Name': 'Sample bay-gated', 'Type': 'CMD', 'Installer': 'scripts/bay.cmd',
'TargetMachineNumbers': ['3201', '3202'],
},
{
'Name': 'Sample host-gated', 'Type': 'BAT', 'Installer': 'scripts/host.bat',
'TargetHostnames': ['WJS-*', 'WJPC0615'],
},
{
'Name': 'Sample always-installs (no detection)', 'Type': 'PS1',
'Script': 'scripts/every.ps1',
},
{
'Name': 'Sample preinstall-flagged', 'Type': 'EXE',
'Installer': 'apps/pre.exe', 'PreEnrollment': True,
'PCTypesStrict': True, 'KillAfterDetection': True,
'PCTypes': ['gea-shopfloor-nocollections'],
},
],
}
REFERENCE_SHARE = '/home/camp/pxe-images/tsgwp00525-v2/shared/dt/shopfloor'
REFERENCE_PREINSTALL = '/home/camp/projects/pxe/playbook/preinstall/preinstall.json'
def test_synthetic_manifest_round_trips_losslessly():
"""The synthetic manifest imports + exports with full behavioral parity."""
results, ok = run_parity([('synthetic', 'runtime', SYNTHETIC)])
result = results[0]
assert result['entries_identical'] == result['entries_total'], result['firstdiff']
assert result['profiles_same'] == result['profiles_total'], result['firstdiff']
assert ok
def test_regvalue_numeric_type_preserved():
"""A DWord RegValue of 1 round-trips as int 1, not the string '1'."""
from plugins.geenforce.importer import build_scope
from plugins.geenforce.serializer import scope_to_manifest
rebuilt = scope_to_manifest(build_scope('synthetic', 'runtime', SYNTHETIC))
dword = next(e for e in rebuilt['Applications']
if e['Name'] == 'Sample Registry DWord')
assert dword['RegValue'] == 1
assert isinstance(dword['RegValue'], int)
@pytest.mark.skipif(not os.path.isdir(REFERENCE_SHARE),
reason='GE-Enforce reference share not present')
def test_reference_share_round_trips_losslessly():
"""Every real on-share manifest round-trips (the live Gate A)."""
manifests = list(discover_share(REFERENCE_SHARE))
if os.path.isfile(REFERENCE_PREINSTALL):
manifests.append(('preinstall', 'preinstall',
load_manifest_file(REFERENCE_PREINSTALL)))
results, ok = run_parity(manifests)
failed = [r for r in results if not r['passed']]
assert ok, f"parity failures: {[(r['scopename'], r['firstdiff']) for r in failed]}"
def test_fixtures_cover_every_pctype():
"""The machine-profile fixtures include one of each imaging pctype."""
labels = {f['pctype'] for f in load_fixtures()}
for pctype in ('gea-shopfloor-collections', 'gea-shopfloor-nocollections',
'gea-shopfloor-common', 'gea-shopfloor-cmm',
'gea-shopfloor-genspect', 'gea-shopfloor-heattreat',
'gea-shopfloor-waxtrace', 'gea-shopfloor-partmarker',
'gea-shopfloor-display'):
assert pctype in labels