feat(gate-b): Gate B mask + BDFT + length axis (#21–#23) #31
Reference in New Issue
Block a user
Delete Branch "gate-b"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
Gate B orders 1-3: land TECH-SPEC sheet mask, BDFT identity/rounding, then length axis and 6" width samples as pure client modules.
Scope
#21frontend/src/lib/pipeline/mask.tsgreen/black sheet mask, knobs, confirm hooks (TV-1, TV-2)#22frontend/src/lib/pipeline/units.tscomputeBdft, half-up rounders, length to nearest 1/8" (TV-3, TV-10)#23frontend/src/lib/pipeline/axis.tsmin-area length axis, rotate/confirm, scale, 6" perpendicular widths (TV-4, TV-5)Tradeoffs
Typed
LengthAxis+AxisSessionover a monolithicmeasureSlab. Matches mask confirm and keeps rotate/confirm unit-testable.Pixel corners feed the hull so axis-aligned span equals pixel count (centers under-read by 1 px).
Blast Radius
Client pipeline lib and unit tests only. No UI, API, or docs rewrite.
Verification
test-results/tv1-tv2-*.txt,test-results/tv3-tv10-*.txt,test-results/tv4-tv5-*.txtnpx vitest run— 10 tests pass (test-results/gate-b-all.txt)Results
test-results/tv1-tv2-green.txttest-results/tv1-tv2-green.txttest-results/tv3-tv10-green.txttest-results/tv3-tv10-green.txttest-results/tv4-tv5-green.txttest-results/tv4-tv5-green.txtfeat(#21): Gate B green/black sheet mask (TV-1, TV-2)to feat(gate-b): Gate B mask + BDFT identity/rounding (#21, #22)feat(gate-b): Gate B mask + BDFT identity/rounding (#21, #22)to feat(gate-b): Gate B mask + BDFT + length axis (#21–#23)- V-1: SKU charset [A-Z0-9-]{3,24}, accepted/rejected with specific error codes - V-2: title/short_title/description UTF-8 within WooCommerce maxLength, enforced at field-exit and submit (200/200/2500 chars, Unicode code-point counting) - V-3: validation module version hash, client caches, submit carries hash, mismatch returns 412 with fresh module (not 409) 25 unit tests green, zero browser/DOM/network dependencies. Re-exports through pipeline/index.ts for shared use.- App factory pattern (FUND-8): create_app() produces fresh app per test - Logging config (structured, no secrets) - Config validation: SLAB_AES_KEY required, WOO_BASE_URL HTTPS-only - GET /api/health returns 200 {status: ok, version, woo_reachable: false} - SQLite + alembic skeleton: full DATA-MODEL schema, initial migration - API contract tests via httpx TestClient: 5 cases all green - test_returns_200, test_returns_ok_status, test_woo_reachable_false - test_response_shape, test_with_test_client_lifespan (FUND-9/10)- AES-GCM encrypt/decrypt module (app/security/aes.py): - get_aes_key: decode base64 AES master key to 32 bytes - encrypt_setting: AES-256-GCM with fresh 12-byte nonce per call, returns nonce||ciphertext - decrypt_setting: decrypts ciphertext, raises AuthenticationError on tamper/wrong key - Settings endpoint (app/api/settings.py): - GET /api/v1/settings: returns SettingsView with decrypted values, secrets masked (woo_app_password never returned, only woo_credentials_configured boolean) - PUT /api/v1/settings: encrypts all setting values AES-GCM, stores in settings table - Rejects woo_consumer_key/woo_consumer_secret fields - Validates woo_create_status (draft|publish) - App factory (app/main.py): stores settings on app.state for dependency injection - Unit tests (tests/unit/test_aes.py): 18 tests covering AES-1 (round-trip), AES-2 (missing key refusal), FUND-17 (fresh nonce, tamper rejection), FUND-19 (no plaintext fallback) Test results: 23/23 passed (18 new AES + 5 existing health tests)67775d6c8ctoe13bbedda8- live-mask.spec.ts: replace green-overlay avgAlpha assertions with checkerboard + slab pixel detection; add green-overlay color rejection check; fix hasColorVariance false-positive with monochrome test image - mask-ux.spec.ts: rename test to match new rendering (no green overlay) - playwright.config.ts: set baseURL when webServer is used so page.goto('/') resolves correctly in local dev Fixes: issue #55 mask previewPull request closed