Skip to main content

Bilko Modul B-1 — GL Foundation Build (2026-06-13)

TL;DR

Bilko ModuleModul B-1 GL Foundation isje builtKOMPLETAN. on branch feature/b1-gl-foundationBackend (commit 687f1d0b,6efb16f9) PR+ #369).frontend The(commiti 69c87cf3 + b1f6401a) izgradeni. GL subsystem is gated behind two feature flags — BILKO_ACCOUNTING_GL and GL_AUTO_POST — both seeded OFF globally. Module A (invoicing) is completely untouched when either flag is off. Proveo independent validation returned PASS (mesh-thr-proveo-103535, 2026-06-13). PR #369 is not yet merged or deployed; it awaits operator sign-off and the [VERIFY-NN] legal-review gate before production auto-posting can be enabled.

Progres & Resume (stanje 2026-06-13)

CEO je pauzirao build ovdje. Ova sekcija dokumentira tacno stanje na dan pauze kako bi svaka buducna sesija mogla nastaviti bez gubitka konteksta.

Napredak — ~60% do radnog B-1

SliceStatusDetalji
Strategija (board)DONE4/4 GO glasova. Board presuda na page 3115.
Vlado posting-pravilaDONE6 dogadjaja, JSONB templates, domain kontrakt potpisan.
Slice 1-3 — GL motor (DB + engine + bridge)DONE + Proveo PASSCommit 687f1d0b (fix od 464c3d14). 16 unit + 12 DB-invariant testova. Trigeri (P0001/P0002/P0004) okidaju uzivo na PG16. Mesh: mesh-thr-proveo-103535-20260613T044650Z.
Slice 4 — Backend kontrolna ploca (9 endpoinata)DONE + Proveo PASSCommit 6efb16f9. 68 GL + 10 HTTP integration testova. Bruto bilanca SD=SC rucno provjereno. Verdict: /tmp/evidence-103547/verdict-v2.json.
Slice 5 — Frontend UIPREOSTAJEVizu, MC #103548. Kontni plan, glavna knjiga, bruto bilanca, temeljnice DRAFT->POSTED ekran.
Slice 6 — Live e2ePREOSTAJEProveo, MC #103549.
Slice 7 — DocsPREOSTAJESkillforge, MC #103550.
Merge PR #369PREOSTAJENakon Slice 6 Proveo PASS gate.

Branch / Deploy stanje (na pauzi)

  • Branch: feature/b1-gl-foundation @ origin 6efb16f9ea0d1a01c88383a75963ad9241294ff0
  • PR #369: NEMERGAN. NE na main. Nista deployano u produkciju.
  • Flagovi:iza BILKO_ACCOUNTING_GL + GL_AUTO_POST flagova  obje default OFF globalno. Modul A (fakturisanje) potpuno netaknut.
Proveo

SliceUAT 4PASS 20/20 (MC #103549), Vlado domain acceptance PRIHVACENO 19/19, Petter (lead) sign-off: merge GO. PR #369 ceka CEO merge odlukudormantan, flag-gated, nema regresije.

B-1 ZAVRSEN (stanje 2026-06-13)

Bilko Modul B-1 — GL Foundation je KOMPLETAN. Backend kontrolna+ plocafrontend izgradjeni, Proveo UAT PASS (summary)20/20), Vlado domain acceptance PRIHVACENO (19/19), Petter (lead) sign-off: merge GO. PR #369 je spreman za CEO merge odluku — flag-gated (BILKO_ACCOUNTING_GL default OFF), Module A potpuno netaknut, nema regresije.

Sta modul radi (iza BILKO_ACCOUNTING_GL flag, default OFF)

Backend (commit 6efb16f9)

  • GL engine: tabele journal_entries, journal_postings, posting_rules, account_mapping, bilko_flags
  • PG trigeri: balance-invariant (P0001), immutability (P0002), idempotency (P0004) — okidaju uzivo na PG16
  • 9 REST endpoinataendpointa na /api/v1/accounting/*,
  • Flyway V85 (permissions):

    permissions
    EndpointOpis
    GET /api/v1/accounting/accountsKontni planseed (account mapping za org)
    GET/PUT /api/v1/accounting/account-mappingKonfiguracija logical-role → account-code
    GET /api/v1/accounting/journalGlavna knjiga — lista journal_entries
    GET /api/v1/accounting/entries/{id}Detalj jednog temeljnicnog zapisa
    GET /api/v1/accounting/trial-balanceBruto bilanca (ΣD=ΣC provjereno)
    POST /api/v1/accounting/entries/{id}/confirmKnjizenje: DRAFT → POSTED (accountant akcija)
    POST /api/v1/accounting/entries/{id}/reverseStorno — append-only, ne brise original
    POST /api/v1/accounting/entries/manualRucni unos temeljnice
    • V85 permissions: accounting:view, accounting:post, accounting:manage_accountsmanage)
    • Bridge eventi: PAYMENT_RECEIVED + CREDIT_NOTE_ISSUED — seeded,PAYMENT/CREDIT_NOTE bridge za(unit-tested; B-2GL_AUTO_POST odlozen.zasebni flag, default OFF)
    • Avans pravila: seeded ali bridge odlozen u B-2.
    • Validacija: 68 GL testovaunit + 10 HTTP integration testova.testova — sve zeleno

    Frontend (commiti 69c87cf3 + b1f6401a)

    • 5 stranica pod app/(dashboard)/accounting/:
      • kontni-plan — tabela Konto | Naziv | Uloga, HR account names (RRiF konvencija)
      • temeljnice — glavna knjiga, paginirani pregled DRAFT/POSTED/REVERSED sa filterima
      • temeljnica/[id] — detalj: postings Duguje/Potrazuje, akcije Potvrdi (DRAFT→POSTED) i Storno
      • nova-temeljnica — rucni unos s live balance-check (ΣD=ΣC prikazano uzivo)
      • bruto-bilanca — per-account totalDebit/totalCredit/saldo, grand totals, asOf filter; ΣD=ΣC indikator
    • Sidebar "Knjigovodstvo" nav sekcija (gating: accountant/admin/owner rola)
    • 404-graceful gating — kada je flag OFF, stranice prikazuju "Ovaj modul nije dostupan" (ne crashaju)
    • 5 lokalizacijskih lokala
    • Playwright spec: apps/e2e/tests/accounting-b1.spec.ts (commitan, spreman za browser run kada je demo SSL dostupan)

    Tok racunovodje

    1. Otvori Kontni plan — pregled konta (logicalRole / accountCode / jurisdikcija, HR RRiF)
    2. Faktura/placanje kreira DRAFT temeljnicu automatski (kada je GL_AUTO_POST ON) ili rucni unos
    3. Potvrdi DRAFT → POSTED (trajna, nepromjenjiva knjizba)
    4. POSTED entry se pojavljuje u Glavnoj knjizi (temeljnice pregled)
    5. Bruto bilanca pokazuje ΣD=ΣC — system-level invariant verificiran trigerom i API-jem
    6. Storno = nova reversing POSTED entry (append-only, original nikad ne brises; cl. 11.3 ZoR)

    Validacija

    SlojRezultatDetalji
    Proveo UAT MC #103547.#103549PASS 20/20Puni lifecycle (DRAFT→POSTED→storno) + gate testovi (flag OFF → 404) + permission negatives (viewer → 403, unbalanced → 400). Bruto bilanca ΣD=ΣC rucno verificirano. Mesh: mesh-thr-proveo-103535-20260613T044650Z. Layer: integration + fe-build (browser odgodjeno — demo SSL nedostupan; spec commitan).
    Vlado domain acceptancePRIHVACENO 19/19Ovlasteni racunovoda. Posting-rule templates (6 dogadjaja, JSONB kontrakt), kontni plan HR, PDV razlaganje po stopi, reversing-entry semantika, append-only nepromjenjivost.
    Petter (lead) sign-offB-1 COMPLETE, merge GOCommit 6efb16f9 backend + 69c87cf3/b1f6401a frontend. 78 testova zeleno. Scope eksplicitno zatvoreno per B-1 DoD.

    Iskrene ogranicenja / odgodeno na B-2

    • Live invoice → auto-DRAFT: bridge unit-tested; e2e nije provjereno (GL_AUTO_POST je OFF zasebni flag; aktivira se u B-2 kada aktiviramo pilot org)
    • Browser-layer E2E: odgodjeno (demo SSL nedostupan za Playwright live run); spec commitan u apps/e2e/tests/accounting-b1.spec.ts
    • Sekvencijalno numerisanje temeljnica: B-2
    • Predujam (avans) bridge kompletno: B-2 (6c knjizenje — netiranje avansa, djelomicni avans)

    RESUME-HEREProduction-activation — Sljedeci korak

    Slice 5 frontendgates (Vizu,prije MCpravog #103548) je tacka nastavka.

    • Build: kontni-plan UI, glavna knjiga view, bruto bilanca view, temeljnice DRAFT->POSTED ekran.
    • Iza BILKO_ACCOUNTING_GL flaga (gated nav — pokazi GL navigaciju samo ako flag ON).
    • Trosi: GET /api/v1/accounting/{accounts,journal,trial-balance,entries/{id}}, POST .../confirm, .../reverse, .../manual.
    • Pattern za Vizu: apps/web/app/(dashboard)/reports/* (kir/kpr/vat/profit-loss), apps/web/lib/api-base.ts (hostname routing app.bilko.cloud → app-api.bilko.cloud).
    • Nakon Slice 5: Slice 6 Proveo live e2e (#103549) → Slice 7 Skillforge docs (#103550) → merge PR #369.

    Gotche (nepregovorljivo na nastavku)racunovodje)

    1. HTTPS-PATOperator push:ukljuci SSHBILKO_ACCOUNTING_GL push= padatrue za uid-501 ("No user exists for uid 501"). Agent gura iskljucivo preko HTTPS-PAT: git push origin HEAD:feature/b1-gl-foundation. Verifikacija: git ls-remote origin feature/b1-gl-foundation ili GitHub API.
    2. git-author-guard: Hook blokira john@ ancestry false-positive na branch push. CEO override: /tmp/git-author-override-<hash> — kreirati u zasebnom bash pozivu PRIJE push poziva (<60s TTL, single-use). Preporuka: neka agent gura, ne John/orchestrator.
    3. session-task-lock (#103522): Moze blokirati mc.js start/update. Koristiti mc.js add ili touch /tmp/session-override-approved-103522.
    4. Proveo dirty working-tree: Cisti checkout git checkout 6efb16f9 -- . prije testa (testira commit sadrzaj, ne local dirty state).
    5. Jedan repo-mutating agent istovremeno: Nema paralelnih agenata koji mutiraju isti repo (parallel-collision lekcija).
    6. CI scope: npx turbo run build + gradlew test + gradlew integrationTest. CI NE pokrace gradlew build/detekt. 4 pre-existing PluginHR XML faila su OK i na main.

    Gateovi prije produkcije (ne preskakati)

    • Operator flip flagova zaimenovanog pilot org.org (GL_AUTO_POST ostaje OFF do gate 2)
    • [VERIFY-NN] OBAVEZNO: pravna provjera na narodne-novine.nn.hr / porezna-uprava.gov.hr provjeraza 10 VERIFY-NN stavki (PDV stopastope/clanci) / clanakanije ZoPDV prije auto-post live.opcionalno
    • VladoImenovan posting-rulesracunovoda kontrakt:design-partner /tmp/evidence-knjigovodstvo/vlado-posting-rule-templates-B1.md(board U2) live walkthrough sign-off

    Cross-linkoviStatus zaPR nastavak#369

    Merge preporuka: GO — dormantan, flag-gated, Module A netaknut, nema regresije. Ceka CEO merge odluku.

    • Spec + Spec/board presuda:page: BookStack page 3115 (B-1 board presuda)
    • PR #369:#369 — feature/b1-gl-foundation (NEMERGAN)
    • MC #103531 (parentparent) build| task)
    • #103547
    • MC(backend Proveo) | #103548 (Slicefrontend 5Vizu) — RESUME-HERE, Vizu frontend)
    • MC| #103549 (SliceUAT) 6 — Proveo live e2e)
    • MC| #103550 (Slice 7 — Skillforge docs)
    • Slice 4 Proveo verdict: /tmp/evidence-103547/verdict-v2.json
    • Resume state source: /tmp/evidence-knjigovodstvo/B1-RESUME-STATE.md

    Architecture

    Database — 5 tables, Flyway migration V84

    TablePurposeKey constraints
    bilko_flags Platform kill-switch flags (no Unleash dependency). org_id IS NULL = global default; non-null = per-org override. Surrogate UUID PK + expression unique index uq_bilko_flags(flag_name, COALESCE(org_id, '00...00')) — required because Postgres 16 does not allow COALESCE in inline PRIMARY KEY/UNIQUE syntax.
    journal_entries GL header (one row per business event). Append-only per Article 11.3 ZoR. UNIQUE(org_id, source_type, source_document_id) — idempotency invariant. Status enum: DRAFT / POSTED / REVERSED. RLS via V75 NULLIF fail-closed canonical pattern.
    journal_postings GL legs (debit/credit rows). Multiple rows per entry. amount > 0, side IN ('DEBIT','CREDIT'). Immutability trigger fires if parent entry is POSTED/REVERSED.
    posting_rules Config-driven Vlado JSONB posting templates. Engine reads rules from here; never hardcodes account numbers. Seeded with R-1 (taxable domestic) and R-3a (EU_41 exempt) on migration. Additional rules added without code changes.
    account_mapping Org-configurable logical-role-to-account-code mapping. Global HR defaults seeded (9 entries). Orgs can override per jurisdiction. Expression unique index uq_am_org_role(COALESCE(org_id,...), jurisdiction, logical_role) — same PG16 fix pattern as bilko_flags.

    Postgres Triggers — 3 enforcement points

    TriggerFunctionWhat it enforcesError code
    trg_je_balance_check fn_je_balance_check Sum(DEBIT) == Sum(CREDIT) at the moment status transitions to POSTED. DRAFT entries are allowed to be unbalanced during assembly. P0002 (balance violation) / P0003 (zero postings)
    trg_je_immutability fn_je_immutability BEFORE UPDATE OR DELETE on journal_entries where OLD.status IN ('POSTED','REVERSED'). DRAFT rows remain mutable. P0001
    trg_jp_immutability fn_jp_immutability BEFORE UPDATE OR DELETE on journal_postings — checks parent entry status; fires if parent is POSTED/REVERSED. P0004

    PostingRuleEngine (Kotlin)

    Located at apps/api/src/main/kotlin/no/alai/bilko/gl/PostingRuleEngine.kt. The engine is config-driven: it reads JSONB posting templates from the posting_rules table and resolves amounts from the incoming GlDocumentData struct. It never computes tax; all net/vat/gross values must originate from the Module A invoice document.

    Key behaviours:

    • Gross check — net + vat must equal gross; mismatch returns REJECTED status (no crash).
    • Rule lookup — matched by (event_type, jurisdiction, vat_exemption_code). Most-specific match wins (rule with explicit vat_exemption_code scores higher than wildcard null match).
    • split_by vat_rate — for multi-rate invoices (Event 2), one CREDIT posting is emitted per distinct VAT rate line, each carrying vat_rate for the B-2 VAT return.
    • No rule found — returns ZA_KONTIRANJE status (no crash, Module A unaffected, accountant must manually post).
    • All drafts — status=DRAFT, requiresAccountantConfirmation=true always set on output.

    GlBridge — A to B integration point

    Located at apps/api/src/main/kotlin/no/alai/bilko/gl/GlBridge.kt. Called from InvoiceService.sendInvoice() inside the existing orgTransaction after the invoice transitions to SENT status.

    • If BILKO_ACCOUNTING_GL=false: early return, engine is never called (MockK verify exactly=0 confirmed by Proveo).
    • If GL_AUTO_POST=false: early return.
    • Both ON: engine called, result persisted as DRAFT via GlRepository.persistDraft().
    • Idempotent: if a journal entry already exists for the same (org, source_type, source_document_id), persistDraft returns null (no duplicate, no exception).
    • Non-throwing: all GL errors are caught and logged; Module A (invoice flow) is never interrupted.

    Posting Rules — Vlado's 6 Events

    Domain contract authored by Vlado Brkanić (certified accountant, design-partner). Scope: outgoing/sales documents only, Croatian jurisdiction (HR). All amounts in EUR. Rates: 25% / 13% / 5% [VERIFY-NN čl.38].

    EventDescriptionDebit legsCredit legs
    1 — SALES_INVOICE_ISSUED (standard) Taxable domestic invoice, VAT 25%, buyer Croatia. accounting_date = delivery/issue date. 1200 Kupci HR (gross) 7600 Prihodi HR (net), 2400 PDV obveza (vat)
    2 — Multi-rate (13%+5%) Same as Event 1 but VAT split across rates. Engine emits one CREDIT posting per rate, each carrying vat_rate. 1200 (gross) 7600 (net), 2400 @13% (vat slice), 2400 @5% (vat slice)
    3a — EU exempt (čl.41) B2B EU supply, zero VAT, report_target=ZP. Precondition: valid VIES VAT-ID. 1201 Kupci EU (gross) 7610 Prihodi EU (net) — no 2400
    3b — Export exempt (čl.45) Third-country export, zero VAT, not reported in ZP. Proof: customs export declaration. 1201 (gross) 7610 (net) — no 2400
    3c — Exempt without deduction right (čl.39/40) Zero VAT. vat_exemption_code preserved for B-2 pro-rata coefficient calculation. 1200/1201 (gross) 7600/7610 (net) — no 2400
    4 — PAYMENT_RECEIVED Cash inflow. Does not touch revenue or VAT accounts. Partial payment leaves receivable open. 1000 Žiro-račun (payment.amount); 1020 Blagajna for cash 1200 Kupci (closes receivable, closes_document_id set)
    5 — CREDIT_NOTE Reversal of Event 1. Reversing entry pattern — all legs inverted. source_type=CREDIT_NOTE, reverses_document_id set. No deletion of original. 7600 Prihodi (net), 2400 PDV (vat) 1200 Kupci (gross)
    6 — Advance (3 steps) 6a Advance received: D 1000 / C 2310 (net) + C 2410 (VAT on advance). VAT liability arises on receipt [VERIFY-NN čl.30/5].
    6b Final invoice on delivery: D 1200 / C 7600 + C 2400. Revenue recognised once.
    6c Netting: D 2310 + D 2410 / C 1200. Advance VAT reversed. Result: 2310/2410/1200 net to zero; no VAT doubling.
    See 6a/6b/6c See 6a/6b/6c

    JSONB Rule Format — R-1 and R-3a examples

    R-1: Taxable domestic invoice (vat_exemption_code is null):

    {
      "event_type": "SALES_INVOICE_ISSUED",
      "jurisdiction": "HR",
      "match": { "vat_exemption_code": null },
      "postings": [
        { "account": "1200", "side": "DEBIT",  "amount_source": "invoice.gross", "analytic": "partner:{invoice.partner_oib}" },
        { "account": "7600", "side": "CREDIT", "amount_source": "invoice.net" },
        { "account": "2400", "side": "CREDIT", "amount_source": "invoice.vat_by_rate", "split_by": "vat_rate", "carry": ["vat_rate"] }
      ],
      "balance_assert": "sum(DEBIT) == sum(CREDIT)",
      "status_on_create": "DRAFT",
      "requires_accountant_confirmation": true
    }

    R-3a: EU-exempt supply (vat_exemption_code = "EU_41"):

    {
      "event_type": "SALES_INVOICE_ISSUED",
      "jurisdiction": "HR",
      "match": { "vat_exemption_code": "EU_41" },
      "report_target": "ZP",
      "postings": [
        { "account": "1201", "side": "DEBIT",  "amount_source": "invoice.gross", "analytic": "partner:{invoice.partner_vat_id}" },
        { "account": "7610", "side": "CREDIT", "amount_source": "invoice.net" }
      ],
      "balance_assert": "sum(DEBIT) == sum(CREDIT)",
      "status_on_create": "DRAFT",
      "requires_accountant_confirmation": true,
      "preconditions": ["partner_vat_id_valid_vies"]
    }

    How to Enable the Module (Operator Runbook)

    The two flags

    FlagDefaultEffect when ON
    BILKO_ACCOUNTING_GL false (global) Enables the GL subsystem for the org. GlBridge checks this first. Without it, the engine is never called. Can be set per-org via bilko_flags (org_id non-null).
    GL_AUTO_POST false (global) When both flags are ON, GlBridge calls the engine and persists a DRAFT journal entry on every invoice send. DRAFT entries appear in the accountant's queue for review and confirmation. The system never auto-transitions a DRAFT to POSTED.

    What happens when both flags are ON

    1. Invoice transitions to SENT in Module A (InvoiceService).
    2. GlBridge.onInvoiceIssued() is called inside the existing orgTransaction.
    3. PostingRuleEngine evaluates the invoice against JSONB rules in posting_rules.
    4. A DRAFT journal entry + postings are persisted. Status = DRAFT, requiresAccountantConfirmation = true.
    5. Accountant reviews the DRAFT in the (future) accounting module UI and transitions to POSTED manually.
    6. If an entry already exists for this invoice (idempotency key), step 4 is a no-op.

    This gate must pass before auto-post can go live in production. Vlado's domain contract contains 10 [VERIFY-NN] annotations referencing Croatian tax law articles (ZoPDV, ZoR). The exact Narodne Novine references must be verified against porezna-uprava.gov.hr / narodne-novine.nn.hr before any POSTED auto-entries are generated for real clients. This is a platform-admin review gate — do not skip.

    Validation Evidence

    Proveo verdict: PASS — Angie Jones, 2026-06-13. Mesh thread: mesh-thr-proveo-103535-20260613T044650Z. Validation report: /tmp/evidence-103535/VALIDATION-REPORT-v2.md.

    Two validation rounds were required:

    • v1 (PARTIAL) — Commit 464c3d14: V84 migration blocked with SQLState 42601. Postgres 16 does not allow COALESCE expressions inside inline PRIMARY KEY / UNIQUE table constraint syntax. Affected 4 locations across bilko_flags and account_mapping.
    • v2 (PASS) — Commit 687f1d0b (fix): Replaced inline COALESCE constraints with surrogate UUID PKs + separate expression unique indexes. All 4 locations corrected.

    DB-invariant proofs (12 sub-tests on live Postgres 16)

    InvariantProbeExpectedSQLStateResult
    Balance trigger (reject) POST entry with D=1000 / C=800, transition to POSTED Exception: "balance violation" P0002 PASS
    Balance trigger (allow) POST entry with D=1250 / C=1250, transition to POSTED No exception PASS
    Idempotency Insert duplicate (org_id, source_type, source_document_id) Unique violation 23505 PASS
    Entry immutability (UPDATE) UPDATE POSTED journal_entry Immutability violation P0001 PASS
    Entry immutability (DELETE) DELETE POSTED journal_entry Immutability violation P0001 PASS
    Posting immutability (UPDATE) UPDATE posting row of POSTED entry Immutability violation P0004 PASS
    Posting immutability (DELETE) DELETE posting row of POSTED entry Immutability violation P0004 PASS
    DRAFT mutability UPDATE on DRAFT journal_entry No exception, persisted PASS
    +4 schema/flag proofs (tables present, indexes present, triggers present, flag seeds confirmed)

    Test counts

    • 16 unit tests: PostingRuleEngineTest (10/10) + GlBridgeTest (6/6) — MockK, no DB.
    • 12 DB-invariant tests: GlInvariantDbTest — full Flyway V1-V84 on postgres:16-alpine Testcontainer.
    • SelfPostingConstraintTest (2/2) — migration regression guard.
    • Pre-existing 4 failures in CountryPlugin XML tests — same on main, unrelated to B-1.

    Flag safety (GlBridgeTest 6/6)

    • BILKO_ACCOUNTING_GL=false: engine never called (MockK verify exactly=0).
    • GL_AUTO_POST=false: engine never called.
    • Both ON + DRAFT: engine called x1, persistDraft called x1.
    • Both ON + ZA_KONTIRANJE result: no persist, no crash.
    • Engine exception: swallowed, Module A unaffected.

    What Is NOT Done Yet (Deferred to next B-1 slice)

    • Frontend kontni-plan UI — accountant-facing account plan management screen.
    • Glavna knjiga / bruto bilanca API endpoints — general ledger summary and trial balance REST endpoints.
    • Accountant DRAFT → POSTED screen — UI for accountant to review and confirm draft journal entries.
    • Remaining posting rule seeds — Events 3b (EXPORT_45), 3c (EXEMPT_39/40), 4 (PAYMENT_RECEIVED), 5 (CREDIT_NOTE), 6a/6b/6c (advance/advance-settlement) are domain-specified but not yet seeded as active rules in posting_rules table.
    • Live end-to-end test — full invoice send with both flags ON, confirming a real DRAFT entry lands in the DB. Recommended for B-2 gate (Proveo open item).
    • [VERIFY-NN] legal review — porezna-uprava.gov.hr article verification gate before production auto-posting is enabled.