Skip to main content

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:

  1. Registration + org creation (now fixed — verify success flow)
  2. Login + JWT token refresh
  3. Invoice creation + PDV calculation
  4. Expense recording + category assignment
  5. Bank CSV import + auto-match
  6. Chart of Accounts CRUD
  7. P&L report generation
  8. Multi-currency invoice with exchange rate lock

Acceptance criteria:

  • bilko-uat-bugs-RERUN.json with 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:

  1. Verify stage Kotlin bilko/api:stage-ab7d50d is production-ready (Sprint 0 landed, registration works, no regression)
  2. Audit prod Cloud SQL instance bilko-db schema state (Flyway version, jmbg/oib columns from V3, ENUM types)
  3. Tag production-ready image: docker tag bilko/api:stage-ab7d50d bilko/api:prod-<sha>
  4. Deploy to prod bilko-api Cloud Run service
  5. Smoke test prod /api/v1/health + registration endpoint
  6. Monitor for 24h (error rate, latency p95)
  7. 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.

Decision authority: CEO (production cutover = revenue surface change)


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:

  1. Add to .gcloudignore:
    apps/api/build/
    apps/api/.gradle/
    **/node_modules/
    **/.next/
    **/dist/
    **/.turbo/
    
  2. Test local: gcloud meta list-files-for-upload (dry-run to see filtered file list)
  3. Verify upload size reduction: target <100MB
  4. PR + merge
  5. 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-db allows connections from 0.0.0.0/0
  • requireSsl=false in 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-factory in build.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 to overdue
  • 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_organizations junction table
  • GET /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.

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