Bilko Sprint Program
Bilko stage UAT + bug-fix sprint program 2026-05-02 (post-CEO Bilko triage)
- UAT Phase 1 Findings
- Express Deletion
- Sprint 0 P0 Registracija
- Web Dockerfile Regression
- Sprint 1-3 + Arch Roadmap
- Open Tech Debt + Followups
- Bilko presjek 2026-08-23 — Talas 1 izvršenje (MC 900154-900158)
UAT Phase 1 Findings
UAT Phase 1 Findings
MC: #10487
Date: 2026-05-02
Stage web: https://bilko-web-stage-dh4m46blja-lz.a.run.app
Stage API: https://bilko-api-stage-dh4m46blja-lz.a.run.app
Verdict: ACCEPT-WITH-FOLLOWUP
Methodology
Three-agent pure UAT discovery on Bilko stage environment (post-Kotlin migration, pre-Express deletion). No build work — observational only.
Team:
- maria-santos — Real-user SMB persona walkthrough (mobile UX + time-to-first-invoice)
- petter-graff — Architecture gap analysis (docs vs code vs schema)
- angie-jones — Functional smoke per epic (INCOMPLETE — deferred to MC #10500)
Top P0 Findings (Blocking Go-Live)
1. Registration Fails — Dual Bug
Root causes:
- DB ENUM type mismatch: Prisma migrations created PostgreSQL ENUM
"UserRole"but Kotlin Flyway V1 declaresVARCHAR(50). Kotlin INSERT with string"owner"→ PostgreSQL rejects with type error. - API field name mismatch: Web sends
organizationName, Kotlin API expectsorgName.
Impact: Zero users can register. Product completely inaccessible to new users.
Evidence:
curl -X POST https://bilko-api-stage-dh4m46blja-lz.a.run.app/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"test@test.ba","password":"test1234","fullName":"Test User","orgName":"Test DOO","country":"BA","baseCurrency":"BAM"}'
→ HTTP 500: {"error":"PSQLException: column \"role\" is of type \"UserRole\"
but expression is of type character varying","code":"INTERNAL_ERROR"}
Followup: MC #10494
2. Invoice Email Send — UI Only, No Dispatch
What: Invoice wizard Step 6 shows email compose fields (To, Subject, Message, "Send me a copy"). InvoiceService.sendInvoice() changes status to "sent" but does NOT send email. The emailData state is never passed to API.
Impact: Customer never receives invoice. User believes invoice was sent. Creates chargeback disputes and relationship damage when client claims "nisam dobio nista."
Evidence: apps/api/src/main/kotlin/no/alai/bilko/services/InvoiceService.kt — no email service injection in DI container. sendInvoice() returns success without SMTP call.
Followup: MC #10495 (Sprint 1 P0)
3. Dead UI Buttons — Receipt Scan + Attach
What:
- "Skeniraj racun" button (
/expenses/new) has noonClickhandler. No camera access, no OCR, no file picker. - "Prikaci racun" (Paperclip) also has no
onClickand no backing<input type="file">.
Impact: The mobile expense entry feature — marketed as a selling point — is non-functional. Field users will abandon immediately. RS/BA tax law requires receipt documentation for deductible expenses; without attachment capability, Bilko cannot support compliance.
Evidence:
apps/web/app/(dashboard)/expenses/new/page.tsx— button is styled<button>with Camera icon but zero interactivity- maria-santos UX report: iPhone Safari VoiceOver announces "Skeniraj racun, button" — activating it does nothing
Followup: MC #10495 (Sprint 1 P0)
4. Bank CSV Format Incompatibility
What: CSV import expects exact format: date,description,amount,reference (ISO 8601 date, comma-separated). Real Bosnian/Serbian banks export semicolon-separated with local date formats: Raiffeisen BA (DD.MM.YYYY), UniCredit RS (local thousand separators), Intesa RS (multi-line headers).
Impact: User exports from Raiffeisen online banking, uploads CSV, gets 0 imported rows. Feature reads as broken. Bank reconciliation is effectively non-functional for Balkan users.
Evidence: apps/api/src/main/kotlin/no/alai/bilko/services/BankingService.kt:303-354 — generic parser, no named bank format presets
Followup: MC #10496 (Sprint 2)
Mobile UX Score: 5/10
Why not lower: Clean UI, readable fonts, BS/SR/HR localization present, adequate color contrast.
Why not higher:
Localization Status
Good news: BS, SR-Latn, SR-Cyrl, HR, EN all have complete translation files. Default sr-Latn. Language switcher (globe icon) present.
Issues:
- sr-Latn dialect inconsistency: Mixes Bosnian and Serbian forms ("dospijeva" [BS] alongside "dospeva" [RS/SR], "mjesec" [BS] vs "mesec" [RS]). File appears half-written for RS, half for BA.
- No Cyrillic variant shown to BA users (but some BA users from RS prefer Cyrillic).
- "Skeniraj racun" label is actively misleading — button does nothing.
Friction Summary
| Severity | Count |
|---|---|
| P0 (blocks all use) | 2 |
| P1 (core workflow broken) | 4 |
| P2 (significant friction/trust damage) | 6 |
| P3 (polish/consistency) | 4 |
Full list: 16 friction points documented in /tmp/bilko-uat-ux-10487.md
Missing Features (vs SMB Expectations)
- No email delivery of invoices (Step 6 UI is cosmetic)
- No OCR receipt scanning (button exists, zero capability)
- No Bosnian/Serbian bank CSV format support
- No SEF integration UI for new users (Settings "Integracije" present but no SEF config screen)
- No registration completion flow (blocked by P0 bugs)
- No offline/draft persistence (wizard loses data on refresh or connectivity loss)
- No payment link/QR code on invoice
- No onboarding validation (flow exists, untestable due to P0 block)
- No mobile-optimized dashboard (charts overflow/compress at 390px)
- No forgot-password email confirmation (shows "Provjerite vas email" but no evidence of dispatch)
Architecture Findings (petter-graff)
Backend Disambiguation: KOTLIN/KTOR
Evidence:
- Stage health check:
{"status":"ok","service":"bilko-api","version":"1.0.0"} - Matches
apps/api/src/main/kotlin/.../routes/HealthRoutes.kt:14-19exactly - Express includes
uptime,timestamp,dbfields (absent from stage) - DEPLOY-MAP.md line 34:
Dockerfile.api-kotlin, imagebilko/api:stage-1f48fdc
Conclusion: Stage is confirmed Kotlin. Express docs are stale.
User Stories Implementation Matrix
15 stories tracked (not 17 — task brief was imprecise). IDs: US-001..004, US-010..012, US-020, US-030..031, US-040, US-050, US-060..061, US-070.
Summary:
- 0 fully implemented
- 8 partial
- 7 with critical gaps
P0 gaps (3):
- US-001: Email verification absent; Serbian CoA seeding not called
- US-003: Invite endpoint not mounted in Kotlin routing
- US-011: SEF stub only (
SEF-STUB-<id>), no real efaktura.gov.rs HTTP
P1 gaps (4):
- US-002: Lockout message English (not Serbian)
- US-004: No multi-org support
- US-012: No automated overdue detection scheduler
- US-050: No ePorezi export format, no PDV reminder
Schema Reality (Prisma vs Kotlin Exposed vs Flyway)
Model count drift:
- Prisma: 22 models
- Kotlin Exposed: ~18 table objects
- Flyway: 18 CREATE TABLE (V1)
- DEPLOY-MAP.md: claims 24 tables on stage DB
Specific drifts:
| Item | Prisma | Kotlin Exposed | Flyway | Gap |
|---|---|---|---|---|
pausal_rates |
PausalRate model | No Exposed Table (data class only) | V4 | GAP: Kotlin may use raw SQL |
archive_jobs |
ArchiveJob model | Comment: "Round 2" | V4 | GAP: ArchiveService uses in-memory, DB table unused |
sefDocumentId, sefAcceptedAt |
Present in Prisma Invoice | Deferred to "Round 2" in Kotlin | Not in Flyway | DRIFT: Prisma has fields, Flyway/Kotlin defer |
Organization address |
Absent | Comment: "Round 2" | Absent | Missing from all three |
Production Readiness Gaps (12 observational)
- No CI pipeline for Kotlin API (Cloud Build deploys web only)
- DB public IP, no SSL/IAM (TD-3, MC #10241 blocker)
- Compliance endpoints auth-gated (
/pausal/ratesreturns 401 — should be public) - No Prometheus metrics endpoint (Kotlin has no
/metricsroute) - No automated overdue invoice scheduler
- Serbian CoA seeding absent from registration
- No SLOs defined or measured
- Rollback runbook references Vercel (wrong platform)
- Email verification not implemented
- SEF stub in production path (legal compliance risk)
- X-Powered-By header absent (consistency gap, not security issue)
- Invite acceptance endpoint missing
Top 5 Architectural Risks
- Split-backend contract drift with zero CI enforcement — Stage Kotlin, prod Express (or nothing). Web pipeline only. Contract drift invisible.
- SEF stub in production — Serbian e-invoicing law mandates real SEF submission. Stub invoices = legally non-compliant.
- Public IP database, no IAM auth —
postgres-socket-factoryabsent, no SSL enforcement (TD-2/TD-3) - No automated schema validation — Prisma/Exposed/Flyway independently maintained; confirmed drifts exist
- Compliance public endpoint regression — Pausal calculator returns 401, blocks landing-page GTM feature
AC1 Followup: angie-jones Functional Smoke
Status: INCOMPLETE
Evidence: /tmp/bilko-uat-bugs-10487.json = 2 bytes ({})
Expected: Structured JSON with ≥8 epic entries, each with screenshots + HAR + repro steps
Followup: MC #10500 (re-run with HAR/screenshots for 8 epics AFTER Sprint 0 lands so login works)
References
Source MCs:
- MC #10487 — UAT Phase 1 (this page)
- MC #10493 — Express deletion
- MC #10494 — Sprint 0 P0 registracija
- MC #10495 — Sprint 1 P0 (SEF/email/receipt)
- MC #10500 — angie-jones re-run
Evidence files:
/tmp/bilko-uat-ux-10487.md(22KB, maria-santos)/tmp/bilko-uat-gap-10487.md(21KB, petter-graff)/tmp/sentinel-verify-10487.md(sentinel verdict)/tmp/proveo-10487-postflight.json
Bilko repo: https://github.com/johnatbasicas/bilko
Express Deletion
Express Deletion (MC #10493)
CEO directive: "Express je tvoj bug, brisi" — 2026-05-02
PR: #39
Status: DONE (merged 2026-05-02)
Outcome: 141 api-express files deleted, 415 npm packages deregistered
Context
Bilko had dual backends for 3 months post-Kotlin migration:
apps/api-express/(12 routes, 9 services, Node.js/TypeScript)apps/api/(Kotlin/Ktor, Exposed ORM, Flyway migrations)
Stage environment: Running Kotlin (bilko/api:stage-1f48fdc)
Prod environment: STILL running Express (bilko-api on Cloud Run, digest 2986d8b0..., port 4000)
CEO decision 2026-05-02: Kotlin is canonical. Express is deprecated. Delete immediately.
Actions Taken
- Branch created:
feat/bilko-kill-express - Directory deleted:
rm -rf apps/api-express/ - Workspace cleanup: Updated
package.jsonworkspaces (removedapps/api-express) - Docs updated:
CLAUDE.md— removed Express backend descriptionBUILD-BLUEPRINT.md— removed Express references
- CI verification:
turbo.jsonandcloudbuild.yamlhad ZERO Express references (no changes needed) - Cloud Run verification: Stage
bilko-api-stageconfirmed Kotlin-safe (revisionstage-1f48fdc) - Package install test:
npm install→ exit 0 (no broken workspace refs)
PR Details
URL: https://github.com/johnatbasicas/bilko/pull/39
Commit: 2c63cdb
Files changed: 141 deletions
Packages removed: 415 npm dependencies
Merge: Squash-merged 2026-05-02 08:51:17 UTC
Root Finding: PROD Still on Express
During Cloud Run inventory (MC #10493 verification by kelsey-hightower):
Stage API (bilko-api-stage):
- Image:
bilko/api:stage-1f48fdc(Kotlin) - Port: 4001
- Healthy
Prod API (bilko-api):
- Image digest:
sha256:2986d8b0...(Express container) - Port: 4000
- Still serving Express backend
Implication: Deleting apps/api-express/ from git does NOT affect prod — prod is running a stale container image. Prod cutover requires separate deployment action.
Followup: MC #10502 (PROD CUTOVER) — H priority, BLOCKER for TD-3 per DEPLOY-MAP.md
Side-Effect: Web Dockerfile Broke
Discovered: 2026-05-02 by kelsey-hightower during MC #10494 deploy verification
Root cause: apps/web/Dockerfile contained:
COPY apps/api-express/package.json ./apps/api-express/
This line was used for web build dependency extraction. When PR #39 deleted apps/api-express/, the COPY directive failed:
Step 8/24 : COPY apps/api-express/package.json ./apps/api-express/
ERROR: failed to compute cache key: "/apps/api-express/package.json" not found: not found
Impact: Web Cloud Build pipeline failed for 3 consecutive builds (regression window: PR #39 merge → PR #41 fix)
Fix: PR #41 (MC #10505) — removed single line from apps/web/Dockerfile
Verification
Tested by:
- codecraft — codebase integrity (no dangling imports)
- kelsey-hightower — Cloud Run service state
Evidence directory: /tmp/evidence-10493/
Smoke tests:
- Stage API health:
curl https://bilko-api-stage-dh4m46blja-lz.a.run.app/api/v1/health→ HTTP 200, Kotlin response shape - Web build: Cloud Build ID
b3bbde85SUCCESS (post-PR #41 fix) - Package install:
npm installexit 0, no workspace errors
Docs Cleanup
Files updated in PR #39:
CLAUDE.md
Before:
Backend: Express (apps/api-express/) — 12 routes, 9 services
Migration: Kotlin in progress (apps/api/)
After:
Backend: Kotlin/Ktor (apps/api/) — canonical since 2026-05-02
BUILD-BLUEPRINT.md
Before:
- Express API (Node.js/TypeScript)
- Kotlin API (migration target)
After:
- Kotlin/Ktor API (canonical)
- Note: Express deleted 2026-05-02 per ADR-021 package rename + CEO directive
Open Items
1. PROD Cutover (MC #10502)
Blocker: TD-3 per DEPLOY-MAP.md
Action required: Deploy Kotlin container to prod bilko-api Cloud Run service
Risk: Prod still on Express means any regression fix in Kotlin (e.g., MC #10494 registracija) does NOT reach prod users
Priority: H
2. Cloud Build API Pipeline
Current state: cloudbuild.yaml deploys web only (no Kotlin API build/deploy)
Risk: Kotlin code changes have no CI gate; manual deploy only
Followup: MC #10498 (Arch roadmap — Kotlin CI pipeline)
References
MCs:
- MC #10493 — Express deletion (this page)
- MC #10502 — PROD CUTOVER (open, H priority)
- MC #10505 — Web Dockerfile regression fix
PRs:
Evidence:
/tmp/evidence-10493/— postflight artifacts- DEPLOY-MAP.md — Cloud Run service inventory
Sprint 0 P0 Registracija
Sprint 0 P0 Registracija (MC #10494)
PR: #40
Status: DONE (merged 2026-05-02)
Outcome: Registration fixed — two bugs resolved in single PR
Problem Statement
Registration endpoint returned HTTP 500 with two independent root causes:
- UserRole ENUM type mismatch — Prisma vs Flyway schema conflict
- Field contract mismatch — web sends
organizationName, Kotlin expectsorgName
Impact: Zero users could register. Product completely inaccessible to new users.
Bug 1: UserRole ENUM Mismatch
Root Cause
Schema conflict:
- Prisma migration (originally used for Express backend): Created PostgreSQL ENUM type
"UserRole"with values('owner', 'admin', 'accountant', 'viewer') - Kotlin Flyway V1: Declared
users.rolecolumn asVARCHAR(50) - Kotlin INSERT:
AuthService.kt:74issuesit[role] = "owner"(String literal)
PostgreSQL rejection:
ERROR: column "role" is of type "UserRole" but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Decision
Align to Kotlin (VARCHAR):
- Reason: Prisma layer dies with Express deletion (MC #10493). Kotlin is canonical.
- Action: Flyway migration to drop ENUM type and revert column to VARCHAR
Fix Applied
New migration: V6__drop_userrole_enum.sql
-- Step 1: ALTER column to VARCHAR (cast existing ENUM values)
ALTER TABLE users
ALTER COLUMN role TYPE VARCHAR(50)
USING role::VARCHAR;
-- Step 2: DROP the ENUM type (now unused)
DROP TYPE IF EXISTS "UserRole";
Evidence: Stage DB migration applied successfully. SELECT pg_type.typname FROM pg_type WHERE typname = 'UserRole' → 0 rows (ENUM type removed).
Bug 2: Field Contract Mismatch (organizationName vs orgName)
Root Cause
Contract divergence:
- Web client (
apps/web/lib/api.ts:112): sendsorganizationName: stringin JSON body - Kotlin API (
apps/api/.../routes/AuthRoutes.kt:74): readsbody["orgName"] as? String
API response:
{"error":"orgName required","code":"BAD_REQUEST"}
Even if the ENUM bug were fixed, registration would still fail at field validation.
Decision
Align Kotlin to web (organizationName):
- Reason: Web is CEO-facing surface. Changing API field name is less risky than changing client-side form.
- Express contract also used
organizationName(contract parity with deprecated backend)
Fix Applied
File: apps/api/src/main/kotlin/no/alai/bilko/routes/AuthRoutes.kt:74
Before:
val orgName = body["orgName"] as? String
?: return@post call.respond(HttpStatusCode.BadRequest,
mapOf("error" to "orgName required", "code" to "BAD_REQUEST"))
After:
val organizationName = body["organizationName"] as? String
?: return@post call.respond(HttpStatusCode.BadRequest,
mapOf("error" to "organizationName required", "code" to "BAD_REQUEST"))
Single-line change. Variable renamed throughout AuthService.register() call chain.
PR Details
URL: https://github.com/johnatbasicas/bilko/pull/40
Commit: ab7d50d
Branch: feat/bilko-sprint0-p0-registracija
Merge: Squash-merged 2026-05-02 09:02:52 UTC
Files changed:
apps/api/src/main/resources/db/migration/V6__drop_userrole_enum.sql(new)apps/api/src/main/kotlin/no/alai/bilko/routes/AuthRoutes.kt(modified)
Deployment
Stage redeploy:
- Image:
bilko/api:stage-ab7d50d(Kotlin with both fixes) - Cloud Run revision:
bilko-api-stage-00002-hbv - Deploy timestamp: 2026-05-02 09:15 UTC
Migration execution:
- Flyway V6 applied automatically on app startup (Flyway baseline V5 → V6 migration detected)
- No manual DB intervention required
Smoke Test
Command:
curl -X POST https://bilko-api-stage-dh4m46blja-lz.a.run.app/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "test-sprint0@alai.no",
"password": "TestPass123!",
"fullName": "Amra Kovacevic",
"organizationName": "Testic DOO",
"country": "BA",
"baseCurrency": "BAM"
}'
Response:
HTTP/1.1 201 Created
{
"userId": "9c218712-4f3a-4d89-bc5e-7a1d8c9e6f2b",
"organizationId": "b8f4ced1-2a3b-4c5d-8e9f-0a1b2c3d4e5f",
"country": "RS",
"baseCurrency": "RSD",
"tokens": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "..."
}
}
Verdict: ✅ Registration successful. User and organization records created. JWT tokens issued.
Verification Evidence
DB state (stage):
SELECT id, email, full_name, role, organization_id
FROM users
WHERE email = 'test-sprint0@alai.no';
Result:
id | email | full_name | role | organization_id
9c218712-4f3a-4d89-bc5e-7a1d8c9e6f2b | test-sprint0@alai.no | Amra Kovacevic | owner | b8f4ced1-...
Organization record:
SELECT id, name, country, base_currency
FROM organizations
WHERE id = 'b8f4ced1-2a3b-4c5d-8e9f-0a1b2c3d4e5f';
Result:
id | name | country | base_currency
b8f4ced1... | Testic DOO | BA | BAM
Note: Response JSON shows RS/RSD but DB has BA/BAM — likely a test data artifact or response serialization bug (non-blocking for registration flow, but flagged for followup).
Open Items
1. Serbian CoA Seeding Still Missing
Context: US-001 AC4 requires Chart of Accounts pre-population on org creation.
Code path: CountryService.kt:220 has seedChartOfAccounts() function, but AuthService.register() does NOT call it.
Impact: New organizations have empty chart of accounts. Users must manually create all account classes.
Followup: MC #10496 (Sprint 2) or separate MC for CoA seeding wire-up.
2. Email Verification Not Implemented
Context: US-001 AC1-2 require email verification flow (send verification email, verify endpoint).
Current state: AuthService.register() issues JWT tokens immediately without email verification.
Security risk: Users can access financial data without verifying email ownership.
Followup: MC #10498 (Arch roadmap) or dedicated security sprint.
References
MCs:
- MC #10494 — Sprint 0 P0 registracija (this page)
- MC #10487 — UAT Phase 1 (discovery)
- MC #10493 — Express deletion (sequencing dependency)
- MC #10496 — Sprint 2 (CoA seeding, multi-org)
PRs:
- #40 — Sprint 0 P0 fix
Evidence:
- Stage API: https://bilko-api-stage-dh4m46blja-lz.a.run.app
- Smoke test output:
/tmp/evidence-10494/(if exists) - USER-STORIES.md: US-001 acceptance criteria
Web Dockerfile Regression
Web Dockerfile Regression (MC #10505)
PR: #41
Status: DONE (merged 2026-05-02)
Root cause: PR #39 deleted apps/api-express/ but didn't clean apps/web/Dockerfile reference
Discovery
Discovered by: kelsey-hightower during MC #10494 deploy verification
Date: 2026-05-02 09:43 UTC
Symptom: Web Cloud Build pipeline failed with:
Step 8/24 : COPY apps/api-express/package.json ./apps/api-express/
ERROR: failed to compute cache key: "/apps/api-express/package.json" not found: not found
Root Cause
Timeline
- PR #39 (MC #10493): Deleted
apps/api-express/directory (141 files, Express backend removal) - Merge: 2026-05-02 08:51 UTC
- Side-effect:
apps/web/Dockerfilestill contained:COPY apps/api-express/package.json ./apps/api-express/ - Next web build: Cloud Build attempted to build web container → COPY directive failed → build aborted
Why the COPY existed
Context: Web Dockerfile used to extract api-express/package.json for dependency caching layer optimization. This was a monorepo build optimization pattern — cache API dependencies separately from web dependencies to improve Docker layer reuse.
Stale pattern: With Express deleted, the COPY line became a dangling reference.
Impact
Regression window: PR #39 merge (08:51 UTC) → PR #41 merge (12:03 UTC) = 3 hours 12 minutes
Failed builds:
- Cloud Build
4f8c2a1d(triggered by MC #10494 branch push) — FAIL - Cloud Build
7b3e9c5f(retry attempt) — FAIL - Cloud Build
a1d8e4b2(manual trigger for diagnosis) — FAIL
Blocked work:
- MC #10494 Sprint 0 P0 deploy (registration fix could not reach stage web)
- Any web-side changes requiring redeployment
User impact: Stage web remained on previous revision (bilko-web-stage-00001-xyz) for 3 hours. Sprint 0 fix was live in API but web could not be updated to reflect registration success flow changes.
Fix
Change Applied
File: apps/web/Dockerfile
Line removed:
COPY apps/api-express/package.json ./apps/api-express/
No replacement needed — web build has no runtime dependency on API package.json. The COPY was purely for Docker cache layer optimization (now obsolete with Express deletion).
PR Details
URL: https://github.com/johnatbasicas/bilko/pull/41
Commit: 23a695e
Branch: feat/bilko-fix-web-dockerfile-api-express-ref
Merge: Squash-merged 2026-05-02 12:03:05 UTC
Files changed:
apps/web/Dockerfile— 1 line deleted
Verification
Local Docker Build Test
Command:
cd ~/ALAI/products/Bilko
docker buildx build -f apps/web/Dockerfile -t bilko-web-test:local .
Result:
[+] Building 127.3s (24/24) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 1.2kB
...
=> exporting to image
=> => exporting layers
=> => writing image sha256:8c7d9e4f...
=> => naming to docker.io/library/bilko-web-test:local
Verdict: ✅ Local build SUCCESS (all 24 steps completed, no COPY error)
Cloud Build Verification
Trigger: PR #41 merge auto-triggered Cloud Build
Build ID: b3bbde85
Status: SUCCESS
Duration: 3m 47s
Image: gcr.io/alai-bilko/web:23a695e
Deploy: Stage web service updated to revision bilko-web-stage-00002-abc
Prevention Protocol
ZAKON Enforcement
ZAKON local-docker-build (active):
Before ANY Dockerfile change PR, agent MUST:
- Build container locally with
docker buildx build- Verify exit code 0 (no build failures)
- Include local build output in PR evidence
Violation in this case: PR #39 (Express deletion) changed workspace structure (deleted apps/api-express/) but did NOT test downstream Dockerfile references before merge.
Corrective action: kelsey-hightower identified the gap; codecraft applied fix; ZAKON already exists (enforcement was manual in this case).
Post-Mortem Insight
Why This Slipped Through PR #39 Review
- Scope misalignment: PR #39 title was "DELETE apps/api-express" — reviewer focus was on Express code removal, not Dockerfile references.
- No cross-directory grep in PR checklist: Express deletion PR did NOT include
grep -r 'api-express' apps/web/step. - Cloud Build web pipeline not triggered by API changes:
cloudbuild.yamltriggers only onapps/web/**path changes. Deletingapps/api-express/did NOT trigger web build → regression invisible until next web change.
Systemic Fix Proposal
MC #10498 (Arch roadmap) should include:
- Pre-merge checklist for monorepo deletions:
grep -r '<deleted_path>' .across all Dockerfiles, CI configs, and scripts - Cloud Build workspace-aware triggers: Trigger web build on ANY monorepo structure change (workspace additions/removals in
package.json) - Local multi-service build gate: Before any workspace deletion PR, run
npm run build(builds ALL workspaces) +docker compose build(if applicable)
Open Items
None — regression fully resolved. Web Cloud Build pipeline healthy.
References
MCs:
- MC #10505 — Web Dockerfile regression (this page)
- MC #10493 — Express deletion (upstream cause)
- MC #10494 — Sprint 0 P0 (blocked by this regression)
- MC #10498 — Arch roadmap (prevention protocol integration)
PRs:
Cloud Build:
- Failed builds:
4f8c2a1d,7b3e9c5f,a1d8e4b2 - Success build:
b3bbde85
Evidence:
- Local Docker build log:
/tmp/evidence-10505/docker-build.log(if saved) - Cloud Build console: https://console.cloud.google.com/cloud-build/builds/b3bbde85
Sprint 1-3 + Arch Roadmap
Sprint 1-3 + Arch Roadmap
Sprint program context: Post-CEO Bilko triage 2026-05-02
Phase: Bug-fix sprint following UAT Phase 1 findings (MC #10487)
Sprint 1 (MC #10495) — P0 Legal + Email + Dead UI
Status: OPEN (H priority)
Owner: TBD (awaiting dispatch)
Scope
Three high-severity bugs blocking go-live:
1. SEF Stub → Real e-Invoicing Integration
Current state: SefService.kt issues stub sefId (SEF-STUB-<id>) and marks invoices as "submitted" without ever contacting efaktura.gov.rs.
Legal risk: Serbian e-invoicing law (2023) mandates submission of all B2B invoices to SEF. Stub invoices = non-compliant. If Kotlin backend promoted to prod without completing this, every "sent" invoice will have fake sefId.
Code location: apps/api/src/main/kotlin/no/alai/bilko/services/SefService.kt:180-200
Round 2 comment in code:
// Round 2 replaces stub with real Ktor CIO HTTP call to efaktura.gov.rs
// Retry queue already persisted — just wire up actual SEF submission
Decision pending CEO:
- Option A: Real efaktura.gov.rs integration (requires SEF credentials, test environment access, XML signature setup)
- Option B: Honest "not yet active" banner in UI + block invoice "send" action until SEF configured (safer short-term path)
Blocker: Without CEO decision, cannot proceed. Integration effort = 3-5 days (XML schema, auth flow, retry handling).
2. Invoice Email Delivery
Current state: Invoice wizard Step 6 shows email compose UI (To, Subject, Message, "Send me a copy"). InvoiceService.sendInvoice() changes invoice status to "sent" but does NOT dispatch email.
Impact: Customer never receives invoice. User believes invoice was sent. Creates chargeback disputes when client says "nisam dobio nista."
Code gap: No email service injection in DI container (DI.kt). No SMTP/Resend/SendGrid integration exists in Kotlin backend.
Evidence: apps/api/src/main/kotlin/no/alai/bilko/services/InvoiceService.kt — sendInvoice() function has no email dispatch logic.
Acceptance criteria:
- Wire email service (Resend recommended — already used in other ALAI products)
- Pass
emailTo,subject,messagefrom wizard Step 6 to API - Attach invoice PDF to email
- Return email delivery confirmation (message ID)
- Show interim banner until wired: "Faktura je snimljena — email slanje još nije aktivno. Preuzmite PDF i pošaljite ručno."
3. Dead UI Buttons — Receipt Scan + Attach
- "Skeniraj racun" (Scan Receipt) — no
onClickhandler, no camera access, no OCR - "Prikaci racun" (Attach Receipt, Paperclip icon) — no
onClick, no file input
Impact: Mobile expense entry — a marketed selling point — is non-functional. RS/BA tax law requires receipt documentation for deductible expenses; without attachment, Bilko cannot support compliance.
UX deception: "Skeniraj racun" button is 120px tall, full-width, purple, most dominant UI element on form. Tapping it does nothing. On iPhone Safari with VoiceOver, announces "Skeniraj racun, button" but zero feedback on activation.
Acceptance criteria:
- Minimum viable (Phase 1): Wire Paperclip button to
<input type="file" accept="image/*,application/pdf">. Connect to expense API upload endpoint. Store receipt URL inexpenses.receipt_urlcolumn. - Future (Phase 2): Wire "Skeniraj racun" to
navigator.mediaDevices.getUserMediafor camera access. Add OCR pipeline (Textract or similar). - Interim: Change "Skeniraj racun" button label to "Skeniraj racun (uskoro)" with
disabledstate. Never show interactive UI for non-functional features.
Sprint 2 (MC #10496) — P1 Core Workflow
Status: OPEN (M priority)
Owner: TBD
Scope
Four P1 gaps affecting core accounting workflows:
1. Chart of Accounts Seeding on Org Creation
Gap: CountryService.seedChartOfAccounts() exists (CountryService.kt:220) but is NOT called from AuthService.register().
Impact: New organizations have empty chart of accounts. US-030 AC1 requires "all 10 account classes present on new Serbian org" — currently fails.
Fix: Add countryService.seedChartOfAccounts(organizationId, country) call after org creation in AuthService.register().
2. Multi-Org Switcher
Gap: Each user has single organizationId. No UI switcher, no API endpoint to switch active org.
Impact: Accountants managing multiple companies (common in SMB Balkans) must log out/in with different emails. US-004 unmet.
Acceptance criteria:
- Add
user_organizationsjunction table (user can belong to multiple orgs) - Add
GET /users/me/organizationsendpoint - Add
POST /users/me/switch-organizationendpoint (updates session active org) - Add org switcher dropdown in top-bar (web)
3. EUR Exchange Rate Fetch from Central Bank
Gap: InvoiceService.getExchangeRate() exists (InvoiceService.kt:972-990) but has TODO comment: "fetch from NBS API for RS, CBBiH for BA."
Current behavior: Returns hardcoded 1.0 or throws error if currency not BAM/RSD.
Impact: Foreign currency invoices (EUR, USD) cannot be created. US-070 partially unmet.
Acceptance criteria:
- Wire to RS central bank XML API:
https://www.nbs.rs/kursnaListaModul/zaXML.faces - Wire to BA central bank:
https://www.cbbh.ba/CurrencyExchange/GetJson - Cache rates daily (store in
exchange_ratestable) - Fallback: prompt for manual entry if API unavailable (US-070 AC3)
4. Bank CSV Parser — Balkan Format Presets
Gap: CSV import expects generic date,description,amount,reference format. Real banks: Raiffeisen BA (semicolon, DD.MM.YYYY), UniCredit RS (local thousand separators), Intesa RS (multi-line headers).
Impact: User exports from real bank, uploads CSV, gets 0 imported rows. Feature reads as broken.
Acceptance criteria:
- Add named bank format presets: Raiffeisen BA, UniCredit RS, Intesa RS, ProCredit BA, OTP BA
- Each preset: delimiter, date format, column positions, header skip count
- OR: CSV mapping UI where user defines which column = date/amount/description
- Store selected bank format in
bank_accounts.import_formatcolumn
Sprint 3 (MC #10497) — P2 Polish
Status: OPEN (L priority)
Owner: TBD
Scope
Three P2 UX polish items:
1. sr-Latn Translation Pass (Dialect Consistency)
Gap: apps/web/messages/sr-Latn.json mixes Bosnian and Serbian forms: "dospijeva" (BS) alongside "dospeva" (RS/SR), "mjesec" vs "mesec", "Postavke" vs "Podešavanja."
Decision: sr-Latn targets RS market (pure Serbian ekavica). Bosnian forms belong in bs.json.
Acceptance criteria:
- Audit
sr-Latn.json— replace Bosnian ijekavica with Serbian ekavica - "mjesec" → "mesec", "sedmično" → "nedeljno", "dospijeva" → "dospeva"
- QA review by Serbian native speaker
2. Mobile UX Micro-Fixes
Gaps (from maria-santos report):
- Invoice wizard step labels hidden on mobile (
hidden sm:inline) - Line item inputs ~70px wide on 390px iPhone (grid-cols-2 sm:grid-cols-4)
- Sidebar overlay no slide animation (raw div, no CSS transition)
- Date picker label misalignment on iOS Safari small screens
- Language switcher tap target 36px (WCAG 2.1 AA requires 44px)
- Amount inputs missing
inputmode="decimal"(iOS numeric keyboard has no decimal separator)
Acceptance criteria: Address top 3 (step labels, line item width, sidebar animation).
3. Dashboard Empty States + Error Message Clarity
Gap: Dashboard shows Recharts widgets with no data → renders blank/broken-looking on first login. No empty state illustrations/guidance.
Acceptance criteria:
- Add empty state for "No invoices yet" (illustration + CTA "Create first invoice")
- Add empty state for "No expenses yet"
- Improve API error messages (currently generic "Registration failed. Please try again." with no timing/retry info)
Arch Roadmap (MC #10498) — Infrastructure + CI
Status: OPEN (M priority)
Owner: TBD
Scope
Four architectural/infra improvements:
1. Kotlin CI Pipeline
Gap: cloudbuild.yaml deploys web only. Kotlin API has no CI (manual deploy only).
Risk: Regression in apps/api/ invisible to CI. If developer pushes breaking change to main, web gets deployed, API does not. Two can silently diverge.
Acceptance criteria:
- Add Cloud Build trigger for
apps/api/**path changes - Build steps:
./gradlew test,./gradlew build,docker build -f Dockerfile.api-kotlin - Push image to GCR
- Deploy to stage Cloud Run
bilko-api-stage(auto) - Deploy to prod requires manual approval (Cloud Build approval gate)
2. RUNBOOK.md Fix (Still References Vercel)
Gap: docs/operations/OPERATIONAL-RUNBOOK.md:23,59,66,120 references Vercel (vercel --prod, vercel rollback, vercel env add) as deployment platform.
Reality: Deployment is GCP Cloud Run + Cloud Build. Vercel not used.
Acceptance criteria:
- Replace Vercel commands with Cloud Run equivalents (
gcloud run deploy,gcloud run revisions list,gcloud run services update-traffic) - Add rollback procedure for Kotlin API (currently only web rollback documented)
- Update SLA report template with actual Cloud Run metrics endpoints
3. .gcloudignore Optimization (MC #10504)
Gap: Cloud Build web deploy uploads 492MB (includes apps/api/build/, .gradle/, node_modules/ from all workspaces).
Impact: Upload timeout on slow connections (3+ minutes on Build step 1/24).
Acceptance criteria:
- Add to
.gcloudignore:apps/api/build/ apps/api/.gradle/ **/node_modules/ **/.next/ **/dist/ - Verify upload size reduction (target <100MB)
4. Cloud Build Trigger Registration (Auto-Deploy on Push)
Gap: Cloud Build triggers are manual (gcloud builds submit) per deploy. No auto-trigger on git push origin main.
Acceptance criteria:
- Register Cloud Build GitHub App trigger for
mainbranch (web) - Register trigger for
mainbranch (api, once Kotlin CI pipeline wired) - Add approval gate for prod deploys (manual Cloud Build approval step)
Dependency Diagram
graph TB
UAT[UAT Phase 1 #10487] --> Express[Express Deletion #10493]
Express --> Sprint0[Sprint 0 #10494]
Sprint0 --> WebDockerfix[Web Dockerfile #10505]
WebDockerfix --> Sprint1[Sprint 1 #10495]
Sprint1 --> Sprint2[Sprint 2 #10496]
Sprint1 --> Sprint3[Sprint 3 #10497]
Sprint0 --> Arch[Arch #10498]
Sprint1 --> AngieRerun[Angie Re-run #10500]
Sprint0 --> ProdCutover[PROD CUTOVER #10502]
Arch --> gcloudignore[.gcloudignore #10504]
style UAT fill:#e1f5ff
style Express fill:#c8e6c9
style Sprint0 fill:#c8e6c9
style WebDockerfix fill:#c8e6c9
style Sprint1 fill:#fff9c4
style Sprint2 fill:#fff9c4
style Sprint3 fill:#fff9c4
style Arch fill:#fff9c4
style ProdCutover fill:#ffccbc
style AngieRerun fill:#f3e5f5
style gcloudignore fill:#f3e5f5
Legend:
- Blue: Discovery (UAT)
- Green: DONE
- Yellow: OPEN
- Orange: BLOCKER
- Purple: Followup
References
MCs:
- MC #10487 — UAT Phase 1
- MC #10493 — Express deletion (DONE)
- MC #10494 — Sprint 0 (DONE)
- MC #10495 — Sprint 1 (OPEN, H)
- MC #10496 — Sprint 2 (OPEN, M)
- MC #10497 — Sprint 3 (OPEN, L)
- MC #10498 — Arch roadmap (OPEN, M)
- MC #10500 — angie-jones re-run (OPEN, M)
- MC #10502 — PROD CUTOVER (OPEN, H, BLOCKER)
- MC #10504 — .gcloudignore (OPEN, M, child of #10498)
- MC #10505 — Web Dockerfile regression (DONE)
Evidence:
/tmp/bilko-uat-ux-10487.md— UX findings (maria-santos)/tmp/bilko-uat-gap-10487.md— Architecture gaps (petter-graff)- USER-STORIES.md — Acceptance criteria source
Open Tech Debt + Followups
Open Tech Debt + Followups
Context: Post-Sprint 0 landscape (2026-05-02)
Sprint program: Bilko stage UAT + bug-fix sprint
Active Followup MCs
MC #10500 — angie-jones Functional Smoke Re-run
Priority: M
Status: OPEN
Owner: TBD
Context: AC1 from UAT Phase 1 (MC #10487) was incomplete. Evidence file /tmp/bilko-uat-bugs-10487.json = 2 bytes ({}). No HAR files, no screenshots, no functional coverage per epic.
Scope:
- Re-run functional smoke test on stage with ALL 8 epics
- Capture evidence per epic: screenshot + HAR + reproduction steps
- Test AFTER Sprint 0 lands (MC #10494) so login works
- Output: structured JSON with ≥8 entries
8 epics to test:
- Registration + org creation (now fixed — verify success flow)
- Login + JWT token refresh
- Invoice creation + PDV calculation
- Expense recording + category assignment
- Bank CSV import + auto-match
- Chart of Accounts CRUD
- P&L report generation
- Multi-currency invoice with exchange rate lock
Acceptance criteria:
bilko-uat-bugs-RERUN.jsonwith structured findings (epic_name, urls_tested, screenshots[], har_files[], repro_steps[])- HAR files saved to
/tmp/bilko-uat-har-<epic_name>.har - Screenshots saved to
/tmp/bilko-uat-screenshot-<epic_name>-<step>.png
Blocker: Sprint 0 must land first (registration must work to proceed past login).
MC #10502 — PROD CUTOVER (Kotlin to Prod)
Priority: H
Status: OPEN
Category: BLOCKER
Context: TD-3 per DEPLOY-MAP.md. Prod bilko-api Cloud Run service is STILL running Express container (digest sha256:2986d8b0..., port 4000). Stage is Kotlin-safe. Cutover blocked.
Scope:
- Verify stage Kotlin
bilko/api:stage-ab7d50dis production-ready (Sprint 0 landed, registration works, no regression) - Audit prod Cloud SQL instance
bilko-dbschema state (Flyway version, jmbg/oib columns from V3, ENUM types) - Tag production-ready image:
docker tag bilko/api:stage-ab7d50d bilko/api:prod-<sha> - Deploy to prod
bilko-apiCloud Run service - Smoke test prod
/api/v1/health+ registration endpoint - Monitor for 24h (error rate, latency p95)
- Document rollback procedure (Cloud Run traffic split to previous Express revision)
Blockers before cutover:
- Sprint 1 SEF decision (CEO choice: real integration vs honest banner) — cannot go to prod with stub if legal risk unacceptable
- Invoice email send (Sprint 1) — cannot market "send invoice" if email doesn't work
- TD-2 resolution (
postgres-socket-factory+ IAM auth) — MC #10240 (currently open)
Risk: Prod still on Express means any bug fix in Kotlin (e.g., registration fix #10494) does NOT reach prod users.
MC #10504 — .gcloudignore Optimization
Priority: M
Status: OPEN
Parent: MC #10498 (Arch roadmap)
Context: Cloud Build web deploy uploads 492MB (includes apps/api/build/, .gradle/, all node_modules/). Upload step times out on slow connections (3+ minutes).
Scope:
- Add to
.gcloudignore:apps/api/build/ apps/api/.gradle/ **/node_modules/ **/.next/ **/dist/ **/.turbo/ - Test local:
gcloud meta list-files-for-upload(dry-run to see filtered file list) - Verify upload size reduction: target <100MB
- PR + merge
- Verify next Cloud Build web deploy upload time <30s
Acceptance criteria:
- Cloud Build upload step duration <30s (down from 180s)
- Build still succeeds (no missing files causing build failures)
Tracked Tech Debt (DEPLOY-MAP.md)
TD-2: Cloud SQL Public IP, No SSL/IAM Auth
MC: #10240 (open)
Severity: MEDIUM (stage), BLOCKER (prod)
Current state:
- Stage DB
bilko-staging-dballows connections from0.0.0.0/0 requireSsl=falsein connection string- Direct TCP to public IP
35.228.33.112:5432 - Password-based auth (secret in env var)
Risk:
- Credential rotation requires redeploy
- No certificate pinning
- Network traffic unencrypted
Required for prod:
- Implement
cloud-sql-socket-factoryinbuild.gradle.kts - Switch to Cloud SQL IAM database authentication (service account-based)
- Remove public IP, use private VPC peering OR Cloud SQL Auth Proxy
Reference: ADR-023-postgresql-on-cloud-sql.md (exists, drives implementation)
TD-3: PROD Still on Express
MC: #10502 (see above)
Severity: BLOCKER
Pre-Existing Blueprint Violations (Score 61/100)
Source: BUILD-BLUEPRINT.md audit 2026-04-29
MEDIUM Violations (3)
1. Package Naming x2
What: Two packages violate ALAI package naming standard (@alai/<name>):
@bilko/api-types(should be@alai/bilko-api-types)@bilko/database(should be@alai/bilko-database)
Impact: Cannot publish to ALAI npm registry (npm.alai.no) without rename.
Blocker for: Multi-repo code sharing (if Bilko utilities needed in other products).
Fix effort: Low (rename in package.json + update imports).
2. Dockerfile Base Image (Chainguard vs Distroless)
What: apps/web/Dockerfile uses cgr.dev/chainguard/node:latest-dev (resolved MC #10442 CVE fix). ALAI standard is gcr.io/distroless/nodejs.
Rationale for deviation: Chainguard swap was emergency CVE-2026-4878 mitigation. Distroless base had unpatched vulnerability at time of fix.
Status: Acceptable deviation (ADR-022 or inline justification should document this).
Action: No immediate change needed, but document rationale in apps/web/Dockerfile comment.
Known Unimplemented Features (From UAT)
1. Email Verification Flow (US-001 AC1-2)
Scope: Registration issues JWT immediately without email verification.
Security risk: Users can access financial data without verifying email ownership.
Required:
- Send verification email on registration (token link)
GET /auth/verify-email?token=<token>endpoint- UI confirmation page
- Block sensitive actions until verified (e.g., invoice send, bank connection)
Priority: P1 (security + compliance)
2. Automated Overdue Invoice Detection (US-012 AC2)
Scope: No scheduler exists to flip invoice status to overdue when due_date < NOW().
Impact: Users never see overdue invoices unless status set manually via API.
Required:
- Cloud Scheduler job (daily at 06:00 UTC)
- Kotlin endpoint
POST /internal/invoices/check-overdue(internal-only, auth bypass) - Query invoices where
status = 'sent' AND due_date < NOW()→ update status tooverdue - Optional: send overdue notification email
Priority: P1 (core workflow)
3. Serbian CoA Seeding (US-001 AC4, US-030 AC1)
Scope: CountryService.seedChartOfAccounts() exists but not called from registration.
Impact: New orgs have empty chart of accounts.
Fix: Add function call in AuthService.register() after org creation.
Priority: P1 (user onboarding)
4. Multi-Org Support (US-004)
Scope: Each user has single organizationId. No switcher.
Impact: Accountants managing multiple companies must log out/in with different emails.
Required:
user_organizationsjunction tableGET /users/me/organizations,POST /users/me/switch-organization- Org switcher dropdown in top-bar
Priority: P1 (SMB accountant use case)
5. Real SEF Integration (US-011)
Scope: Stub sefId (SEF-STUB-<id>) issued, no real efaktura.gov.rs HTTP.
Legal risk: Serbian e-invoicing law mandates real submission.
Decision pending: CEO choice (real integration vs honest banner).
Priority: P0 (legal compliance) or DEFERRED (if banner chosen)
Post-Sprint 0 Metrics
Completed Work (2026-05-02)
- 3 PRs merged: #39 (Express deletion), #40 (Sprint 0 P0), #41 (Dockerfile fix)
- 2 P0 bugs fixed: Registration ENUM + field contract
- 141 files deleted: Express backend removal
- 1 regression resolved: Web Dockerfile COPY reference
Open Bilko MCs (Post-Cleanup)
Total: 45 MCs remaining (down from 69 pre-cleanup, per MC #10300 sweep)
By priority:
- H: 8 (includes #10495, #10502)
- M: 22 (includes #10496, #10498, #10500, #10504)
- L: 15 (includes #10497)
By status:
- Open: 42
- In-progress: 3
- Blocked: 0 (after CEO triage)
References
MCs:
- MC #10487 — UAT Phase 1 (discovery)
- MC #10493 — Express deletion (DONE)
- MC #10494 — Sprint 0 P0 (DONE)
- MC #10495 — Sprint 1 (OPEN)
- MC #10496 — Sprint 2 (OPEN)
- MC #10497 — Sprint 3 (OPEN)
- MC #10498 — Arch roadmap (OPEN)
- MC #10500 — angie-jones re-run (OPEN)
- MC #10502 — PROD CUTOVER (OPEN, BLOCKER)
- MC #10504 — .gcloudignore (OPEN)
- MC #10240 — postgres-socket-factory (OPEN, TD-2)
Docs:
- DEPLOY-MAP.md — Cloud Run inventory + TD tracking
- BUILD-BLUEPRINT.md — Package standards + violations
- USER-STORIES.md — Acceptance criteria source
- ADR-023 — PostgreSQL on Cloud SQL (IAM auth guidance)
Evidence:
/tmp/bilko-uat-ux-10487.md(maria-santos UX report)/tmp/bilko-uat-gap-10487.md(petter-graff architecture gaps)
Bilko repo: https://github.com/johnatbasicas/bilko
Bilko presjek 2026-08-23 — Talas 1 izvršenje (MC 900154-900158)
Bilko presjek 2026-08-23 — Talas 1 izvršenje (MC #900154–#900158)
Izvor: timska analiza 5 arhitekata (Petter Graff lead) nad azdo/main@1d58cbb6 + izvedbeni plan.
Trajni dokazi: ~/system/evidence/bilko-presjek-20260823/ (a1–a4, FINAL, PLAN); artifact izvještaj kod CEO-a.
Talas 1 — stanje
| MC | Stavka | Stanje 23.08. |
|---|---|---|
| #900154 | RLS RESTRICTIVE odluka | Securion audit: NO-GO — runtime rola bilko_admin je BYPASSRLS (živo potvrđeno DATABASE_USER), RLS bez efekta na živoj konekciji; 7 preduslova + soak metrike u auditu. ADR-017 addendum u PR #388. |
| #900155 | Prepis SECURITY-ARCHITECTURE.md | Novi sadržaj (stvarni RLS mehanizam, bez Prisma/Express) u PR #388, grana fix/900155-security-docs-pack@215b4ac3. |
| #900156 | Mobile PRD blokatori | Retroaktivni Securion audit (grana A): PASS-uz-popravke — F1 tokeni u Zustand (kritično, blokira distribuciju), F2 OCR bez legal review, F4 demo-login u prod EAS profilu. Korekcija istorije: #102962/#102989 pokrivali samo backend. Status dokument ažuriran u PR #388. |
| #900157 | Mobile CI gate | Forged prompt (5-člani panel, 5/5 dissent) + Mehanik CLEAR TO DISPATCH; izvršenje faza 1 kod pi-orchestratora (worktree bilko-900157-mobile-ci, azdo/main@337d0572). |
| #900158 | DEMO_MODE runtime probe | Izvršeno: DEMO_MODE=true globalno na živoj reviziji; korekcija — aktivni HR e-račun put je Sveračun (SVERACUN_HR_LIVE=true, TEST API), ne Storecove mock. Lansirni uslovi zapisani u ~/system/evidence/900158/ZAKLJUCAK.md. |
Sistemski nalazi usput (zapisani, ne popravljani — radni dogovor t.12)
- qa-19 pisac vs mc.js čitač — različiti session resolveri.
detectActor()vraća 'john' za svaki proces bezCLAUDE_AGENT_IDna Studiju.- ZAKON #20 marker
/tmp/alai-subagent-contextima čitača bez pisca — subagenti blokirani kao John; izvršenje rutirano kroz pi-orchestrator. - "Deploy landing-hr → bilko.cloud (CF Pages)" pada na svih zadnjih 5 main buildova (CI Gates pritom zelen).
- BUILD-BLUEPRINT.md §9 stale (GCP umjesto Azure), bez pomena mobile.
Sljedeće (Talas 1 rep + priprema Talasa 2)
- #900157 D3/D4: pozitivan run + negativna kontrola s nezavisnim verifikatorom (čita ADO UI direktno).
- Mobile F1+F4 fix (build task), runtime DB rola bez BYPASSRLS (novi forge ciklus).
- PR #388: drugi-vendor review (gemini CI job) → merge.
Zatvaranje Talasa 1 — 2026-08-23 (~13:50)
- PR #388 MERGOVAN (merge commit
c3cec5cc): SECURITY-ARCHITECTURE prepis (#900155), ADR-017 NO-GO addendum (#900154), mobile status audit zapis (#900156). - PR #389 MERGOVAN (merge commit
1ae7dee8): blocking gate_mobile job (#900157) — kanarinac dokazan u OBA smjera na istoj definiciji joba (run 1275 crven s izvršenim koracima; run 1277 zelen sa svih 5 koraka izvršeno; run 1274/1276 dokazuju path-skip semantiku). Nezavisna verifikacija: svih 7 tvrdnji CONFIRMED (evidence/900157/independent-verification-2026-08-23.md). - #900158: DEMO_MODE probe izvršen s korekcijom (aktivni HR put je Sveračun TEST API; Stripe test ključ; lansirni uslovi u evidence/900158/ZAKLJUCAK.md).
- Zatvaranje kroz writer≠closer peer put (closer: pi-orchestrator).
- Formalno zatvaranje izvršeno kroz pi closer put: 2026-08-23T17:40:42.621Z (qa-19 PASS svih 5, CEO acceptance upisan).