Skip to content

XBRL Filing (ACRA)

1. Document Control

Document TitleSingapore ACRA XBRL Filing Automation
Document IDSOP-ACC-004
Version1.0 (Draft for Automation Build)
Effective Date[Insert Date]
Review Date[Insert Date + 12 months]
Document OwnerHead of Regulatory Filings
ApproverManaging Director
StatusDraft

Version History

VersionDateAuthorChangesApproved By
1.0[Insert Date][Insert Author]Initial SOP for the AI-assisted XBRL filing module (BreezyCorp Phase 2)[Insert Approver]

Distribution

Role TitleAccess Rights
Client ApproverRead-only
XBRL PreparerEdit
XBRL ReviewerEdit
Senior AccountantEdit (no Mark Filed)
Platform AdminEdit
Quality ReviewerRead-only
AI Workflow DeveloperRead-only

2. Purpose and Scope

2A. Process Overview for New Staff

What is this process?

This SOP defines the controlled workflow for filing financial statements with ACRA in XBRL format, using the AI-assisted XBRL Filing Engine (XFE). The XFE orchestrates: source document ingestion (DOCX or PDF financial statement, or direct hand-off from a FsGeneratedStatement); line-item extraction; ACRA taxonomy element mapping (fuzzy match + human confirmation); 144-rule validation; BizFinx XLSX and XBRL XML output — with two non-overridable gates before any output is produced.

When does this process occur?

This process is triggered when a client requires ACRA filing of an annual or interim financial statement. One XbrlFiling is created per client per period. Multiple filings for the same client (e.g. FY2023 and FY2024) coexist; each is independent and pins its own taxonomy version at creation time.

What are the deliverables?

  • Confirmed line-item-to-element mapping for every monetary fact in the financial statement
  • 144-rule validation result set with all ERROR-severity rules passed
  • BizFinx Excel workbook (multi-sheet) for upload to BizFinx Preparation Tool
  • XBRL XML instance document for direct submission
  • Optional client portal sign-off before submission
  • ACRA filing reference captured on Mark Filed
  • Archived filing record with immutable audit trail

Who is involved?

  • XBRL Preparer (XBRL_PREPARER)
  • XBRL Reviewer (XBRL_REVIEWER)
  • Senior Accountant (SENIOR_ACCOUNTANT)
  • Client Approver (CLIENT_APPROVER)
  • XFE (orchestration, ingestion, mapping suggestion engine, validation engine, exporters)

Primary Compliance Areas (Singapore)

  • ACRA XBRL filing requirement — most Singapore-incorporated companies must file financial statements in XBRL alongside annual returns.
  • ACRA Taxonomy 2026 v1.0 — 1871 elements; the only taxonomy version installed in the constitution at v1.0 of this SOP. Future versions are loadable side-by-side via loadTaxonomy(version).
  • ACRA Business Rules 2026 v1.0 — 144 validation rules. Categories: arithmetical, totalling, cross-statement consistency, mandatory presence, sign convention, format.
  • Entry-point variantsFULL_XBRL, SIMPLIFIED_XBRL, FSH_BANKS, FSH_INSURANCE. Pinned per filing at creation.
  • Entity typeNON_LISTED_COMPANY_FULL, SMALLER_NON_LISTED_COMPANY, SGX_LISTED, MAS_LICENSED_BANK, MAS_LICENSED_INSURER.
  • Accounting standardSFRS, SFRS_SE, IFRS.

Compliance Horizon

This SOP is designed so that no XBRL output leaves the system without:

  1. Every tag mapping confirmed by an authenticated staff user.
  2. Validation run with zero ERROR-severity failures.

These are the cursorrules non-negotiables — they live in code (packages/xbrl/src/export-gate.ts), in tests (__tests__/export-gate.test.ts, __tests__/no-element-literals.test.ts), and in this SOP. There is no override path.


3. Definitions and Abbreviations

Term/AbbreviationDefinition
XFEXBRL Filing Engine — the automation layer that orchestrates ingestion, mapping, validation, export
ACRAAccounting and Corporate Regulatory Authority (Singapore)
BizFinxACRA's filing preparation tool; accepts a multi-sheet Excel workbook for upload
XBRLeXtensible Business Reporting Language — standardised tagging format for financial data
Entry PointAn ACRA taxonomy variant: FULL_XBRL (default for non-listed companies), SIMPLIFIED_XBRL, FSH_BANKS, FSH_INSURANCE
Entity TypeFiling category: non-listed full, smaller non-listed, SGX-listed, MAS-licensed bank, MAS-licensed insurer
ElementA single taxonomy concept (e.g. sg-as_TotalAssets). Each carries data_type, period_type (instant / duration), balance (debit / credit)
Line ItemOne extracted monetary or string fact from the source document, awaiting tag mapping
Tag MappingThe decision that a given line item maps to a given element — requires human confirmation
ConstitutionImmutable JSON in packages/xbrl/constitution/: taxonomy_acra_2026_v1.json, validation_rules_acra_2026_v1.json, mapping_library.json
Synonym Librarymapping_library.json — fuzzy-match seed of label → element_id pairs. Writable at runtime; every write is audited
UENUnique Entity Number — Singapore company identifier
ALAudit Logger — AuditEvent rows with actor, action, payload, timestamp
Export GateassertExportAllowed() in packages/xbrl/src/export-gate.ts. Throws XbrlExportBlockedError (HTTP 422) on rule 2 or 3 failure

4. Roles and Responsibilities

RoleResponsibilitiesCompetency Requirements
XBRL PreparerCreate filing; ingest DOCX/PDF or pull from FS engagement; confirm or override every tag mapping suggestionACRA taxonomy familiarity; willingness to refuse a fuzzy match that doesn't fit
XBRL ReviewerAll preparer rights + run validation; export BizFinx XLSX / XBRL XML; mark filed; add new synonyms to the mapping librarySenior XBRL judgment; understanding that synonym writes affect future filings for every client
Senior AccountantAll XBRL Preparer + XBRL Reviewer rights except MARK_XBRL_FILED — reserved for XBRL_REVIEWER / PLATFORM_ADMINCross-product judgment (FS + XBRL)
Client ApproverReview the filing summary + statement-level previews via the portal magic link; Approve or Request Revision before submissionFamiliarity with the entity's UEN and the period being filed
XFE (system)DOCX/PDF parsing, line-item normalisation, fuzzy-match mapping suggestion, 144-rule evaluation, BizFinx XLSX & XBRL XML rendering, export gateConstitution loaders + status machine + worker handlers

Segregation of Duties (SoD) Controls

  • The export gate is enforced at the service layer and in worker handlers (defence in depth). No code path produces an output artifact without assertExportAllowed() passing.
  • MARK_XBRL_FILED is restricted to XBRL_REVIEWER and PLATFORM_ADMIN. Even SENIOR_ACCOUNTANT cannot mark a filing as accepted by ACRA. The boundary intentionally matches human accountability with the regulator.
  • ADD_MAPPING_SYNONYM is restricted to XBRL_REVIEWER, SENIOR_ACCOUNTANT, PLATFORM_ADMIN. Each synonym write is AuditEvent-logged with the staff user id, label, and element id. The library file is shared across all clients — a synonym added for one client affects future filings for every client (see Risk §11 and the Phase 4 per-client override backlog).
  • Tag-mapping confirmations require an authenticated staff user. No background job or API path is permitted to set confirmedById automatically.

5. Prerequisites and Entry Conditions

Before commencing this process, verify the following conditions are met:

  1. Client master record exists with XBRL_FILING in enabledProducts.
  2. Client.xbrlConfig is populated with entityType, defaultEntryPoint, taxonomyVersion (e.g. acra_2026_v1), accountingStandard, and uen.
  3. Staff users hold the appropriate role: XBRL_PREPARER to drive the filing through to validation; XBRL_REVIEWER to export and mark filed.
  4. The source document for ingestion exists — either a financial-statement DOCX/PDF, or a FsGeneratedStatement in a FINANCIAL_STATEMENTS engagement on the same client (cross-product Phase 3 path).

Entry Checklist

  • [ ] Filing ID convention confirmed (auto-generated UUID; surfaced in URL as /dashboard/xbrl/<filingId>)
  • [ ] Period start and period end captured as YYYY-MM-DD
  • [ ] Entry point chosen (FULL_XBRL typical for non-listed full companies)
  • [ ] Entity type chosen
  • [ ] Accounting standard chosen
  • [ ] Taxonomy version pinned (must exist in the constitution; default acra_2026_v1)
  • [ ] Audit logging enabled

6. Detailed Process Flow

Process Map (high-level phases)

  1. CREATE — Filing creation with pinned taxonomy version
  2. INGEST — Source document upload → line-item extraction
  3. MAP — Per-line-item element confirmation (fuzzy-match suggested; human-confirmed)
  4. VALIDATE — Run the 144 ACRA business rules
  5. EXPORT — BizFinx XLSX or XBRL XML (gated on Rule 2 + Rule 3)
  6. REVIEW — Optional client portal sign-off
  7. FILE — Mark filed against ACRA submission reference
  8. ARCHIVE — Sealed filing, retained per policy

Controlled States (State Machine)

The filing walks through eight states. See packages/xbrl/src/status-transitions.ts for the canonical transition matrix.

DRAFT → DOCUMENTS_INGESTED → MAPPING_IN_PROGRESS → VALIDATION_PASSED → EXPORTED → FILED → ARCHIVED
                                                ↘ VALIDATION_FAILED ↺ MAPPING_IN_PROGRESS (recovery)
VALIDATION_PASSED → MAPPING_IN_PROGRESS (revert a confirmation)
EXPORTED          → MAPPING_IN_PROGRESS (back-out before filing)

The Five Non-Negotiable Rules (from xbrl-saas/cursorrules)

These rules survive the migration unchanged. They are gating, not aspirational.

  1. No taxonomy literal outside constitution + loader. All element references flow through TaxonomyLookup. Asserted by __tests__/no-element-literals.test.ts which greps packages/xbrl/src/ for ACRA element prefixes.
  2. No XBRL output without passing validation. assertExportAllowed() raises VALIDATION_ERROR_PRESENT (HTTP 422) if any XbrlValidationResult row has severity = ERROR AND passed = false.
  3. Every tag mapping must be human-confirmed. Same gate raises UNCONFIRMED_TAG_MAPPING if any XbrlTagMapping.confirmedById IS NULL. No code path auto-confirms.
  4. Taxonomy version is first-class. loadTaxonomy(version) throws XbrlUnknownTaxonomyVersionError for unknown versions. XbrlFiling.taxonomyVersion is required at create and immutable thereafter.
  5. Run the regression suite before push. pnpm --filter @breezycorp/xbrl test includes the gate tests, the no-literals test, the unknown-version test, and (when fixtures land) the golden BizFinx snapshot.

Step 1.0: Create Filing (S0 → DRAFT)

Process Phase: CREATE

Actor: XBRL Preparer

Action Description

Create a new XbrlFiling for the client + period. Pin entry point, entity type, accounting standard, and taxonomy version at create time.

Statutory Basis

The pinned taxonomy version is the contract with the regulator. ACRA may release a new taxonomy mid-year; pinning per filing means a filing started in 2026 can ship against acra_2026_v1 even after acra_2027_v1 lands.

Inputs

Field NameFormatSourceValidation Rule
clientIdUUIDClient masterMust have XBRL_FILING enabled
periodStartYYYY-MM-DDUser input< periodEnd
periodEndYYYY-MM-DDUser input> periodStart
entryPointEnumxbrlConfig defaultOne of FULL_XBRL / SIMPLIFIED_XBRL / FSH_BANKS / FSH_INSURANCE
entityTypeEnumxbrlConfig defaultOne of the 5 entity types
accountingStandardEnumxbrlConfig defaultSFRS / SFRS_SE / IFRS
taxonomyVersionStringxbrlConfig defaultMust exist in packages/xbrl/constitution/
fsEngagementIdUUID (nullable)Optional cross-linkSame clientId; must exist

Micro-Steps

  1. Open /dashboard/xbrl/new (or POST /ops/xbrl/filings).
  2. Fill in header. Dropdowns default from Client.xbrlConfig.
  3. Submit. Filing created in DRAFT. taxonomyVersion is now immutable.

Validation and Control Checks

  • Check 1: Caller holds MANAGE_XBRL_FILING.
  • Check 2: taxonomyVersion is loadable (loadTaxonomy(version) does not throw). If unknown → 400.
  • Check 3: No duplicate (clientId, periodEnd, taxonomyVersion) filing exists.

Decision Points and Branching Logic

  • IF enabledProducts does not include XBRL_FILING, THEN request rejected with 400.
  • IF an fsEngagementId is supplied, THEN the cross-product hand-off path is used at the ingestion step (POST /from-fs-engagement — Phase 3).
  • ELSE standard DOCX/PDF path.

System Interaction

  • System: API (/ops/xbrl/filings)
  • Action: Insert XbrlFiling row, emit AuditEvent xbrl.filing.created

Data Storage and Evidence

  • XbrlFiling row with versionNo = 1, status = DRAFT, taxonomyVersion pinned.

Acceptance Criteria

  • [ ] Filing created in DRAFT
  • [ ] Audit log shows xbrl.filing.created with pinned taxonomyVersion

Step 2.0: Ingest Source Document (DRAFT → DOCUMENTS_INGESTED → MAPPING_IN_PROGRESS)

Process Phase: INGEST

Actor: XBRL Preparer

Action Description

Upload the financial statement DOCX or PDF. The ingest-fs-document and extract-line-items handlers run sequentially: compute SHA-256, persist XbrlSourceDocument, parse tables (DOCX via mammoth, PDF via pdf-parse + heuristics), normalise amounts, and persist XbrlLineItem rows. Then suggest-tag-mappings runs and produces XbrlTagMapping rows (all unconfirmed) via the exact-match-then-fuzzy-match cascade.

Statutory Basis

N/A (data capture)

Inputs

InputFormatNotes
Source documentDOCX / PDFMax ~10 MB
Statement typeInferredbalance_sheet / income_statement / cash_flow / equity_changes / notes

Cross-product variant (Phase 3): when fsEngagementId is set, POST /ops/xbrl/filings/:id/from-fs-engagement skips the DOCX parse and expands the latest FsGeneratedStatement.statementsJson directly into XbrlLineItem rows.

Micro-Steps

  1. Open the filing; click Upload source document.
  2. Drag-drop the DOCX or PDF. Multipart upload to POST /ops/xbrl/filings/:id/documents.
  3. The handler:
    • Persists the bytes via the File model with key prefix xbrl/<clientId>/<filingId>/source.{docx,pdf}
    • Computes SHA-256
    • Inserts XbrlSourceDocument with parseStatus = PENDING
    • Enqueues extract-line-items
  4. extract-line-items:
    • Reads the file from S3
    • Parses tables and text; normalises numbers (strip commas, parentheses → negative, currency symbols)
    • Inserts XbrlLineItem rows: {statement, label, valueCurrent, valuePrior, sourcePage, sourceLine}
    • Updates XbrlSourceDocument.parseStatus = PARSED (or FAILED)
    • Transitions filing DRAFT → DOCUMENTS_INGESTED
    • Enqueues suggest-tag-mappings
  5. suggest-tag-mappings:
    • Iterates every XbrlLineItem without a confirmed mapping
    • Exact-match against mapping_library.json synonyms (case-insensitive)
    • On miss, fuzzy-match against taxonomy element labels filtered by applicable_entry_points and taxonomy_section
    • Persists XbrlTagMapping with confirmedById = NULL, alternatives populated (top-N candidates for the UI)
    • Transitions filing DOCUMENTS_INGESTED → MAPPING_IN_PROGRESS

Validation and Control Checks

  • Check 1: SHA-256 deduplication — re-uploading the same file is idempotent.
  • Check 2: parseStatus = PARSED before mapping suggestions run.
  • Check 3: Element IDs in suggestions are real (must exist in the pinned taxonomy version).

Decision Points and Branching Logic

  • IF parse fails (DOCX has no tables, PDF has unreadable layout), THEN parseStatus = FAILED and the filing stays at DRAFT. Reviewer either fixes the source file or, in the cross-product path, switches to from-fs-engagement.

System Interaction

  • System: API (POST /ops/xbrl/filings/:id/documents), worker (ingest-fs-document, extract-line-items, suggest-tag-mappings), S3, constitution loaders.

Data Storage and Evidence

  • XbrlSourceDocument row with sha256, parse status, page count.
  • XbrlLineItem rows.
  • XbrlTagMapping rows (unconfirmed) with alternatives for the UI.
  • AuditEvent xbrl.documents.ingested.

Common Mistakes to Avoke

  • Do not upload a scanned PDF of a financial statement. The line-item extractor needs textual tables; a flat raster will yield zero line items.
  • Do not upload a multi-period working file. The extractor expects one current period and one prior period.

Acceptance Criteria

  • [ ] Filing reaches MAPPING_IN_PROGRESS
  • [ ] Every XbrlLineItem has an XbrlTagMapping (unconfirmed) with a top suggestion

Step 3.0: Confirm Tag Mappings (MAPPING_IN_PROGRESS)

Process Phase: MAP

Actor: XBRL Preparer

Action Description

For every line item, confirm the suggested element or pick an alternative. This is the Rule 3 gate — no line item leaves this step without an authenticated staff user against confirmedById.

Statutory Basis

Every monetary fact filed with ACRA must be associated with a specific taxonomy element with the correct data_type, period_type, and balance semantics. Wrong element = invalid filing.

Micro-Steps

  1. Open the Mappings tab. Master-detail layout: line-items list on the left, element-confirmation panel on the right.
  2. Pick a line item. The panel shows:
    • Source page + line reference
    • Current period and prior period values
    • Top suggestion with confidence
    • Top-N alternatives (alternatives[] from the suggestion engine)
    • An element search box (filtered by entry point + statement section)
  3. Confirm or override:
    • Confirm — accepts the current suggestion; sets confirmedById and confirmedAt.
    • Pick alternative — sets elementId to the chosen alternative; confirms.
    • Search and pick — searches the taxonomy; sets elementId; confirms.
    • "Save as synonym" — additionally appends {label, elementId} to mapping_library.json. Requires ADD_MAPPING_SYNONYM permission. Each write is audited.
  4. To unconfirm a row, click the unconfirm button. confirmedById and confirmedAt clear. The export gate will block until re-confirmed.

Validation and Control Checks

  • Check 1: elementId must exist in the pinned taxonomy version. UI dropdown is constrained.
  • Check 2: confirmedById is set to an authenticated staff user. No background job is permitted to set this.
  • Check 3: Save-as-synonym requires the higher ADD_MAPPING_SYNONYM action.

Decision Points and Branching Logic

  • IF the line item describes a concept not present in the taxonomy, THEN revisit the source document — the extractor may have produced a row from a custom disclosure that should be merged or dropped.
  • IF mapping_library.json has a high-confidence existing synonym for the label, the suggestion is HIGH and one confirmation closes the row.

System Interaction

  • System: API (POST /ops/xbrl/filings/:id/mappings/:lineItemId, DELETE same), worker (none — synchronous), constitution.

Data Storage and Evidence

  • XbrlTagMapping row with elementId, confidence, alternatives, explanation, confirmedById, confirmedAt.
  • AuditEvent xbrl.mapping.confirmed per row.
  • AuditEvent xbrl.mapping.synonym_added (also) when save-as-synonym fires.

Acceptance Criteria

  • [ ] Every XbrlLineItem has an XbrlTagMapping with confirmedById != NULL
  • [ ] Filing is ready for validation

Step 4.0: Run Validation (MAPPING_IN_PROGRESS → VALIDATION_PASSED | VALIDATION_FAILED)

Process Phase: VALIDATE

Actor: XBRL Reviewer (or Senior Accountant)

Action Description

Execute the 144 ACRA business rules against the confirmed mappings. Results are written as XbrlValidationResult rows. The filing transitions to VALIDATION_PASSED if no ERROR-severity rule failed, otherwise VALIDATION_FAILED.

Statutory Basis

The 144 rules are the published ACRA Business Rules 2026 v1.0. Categories include:

  • arithmetical — addition / subtraction consistency within a statement
  • totalling — section subtotals equal the sum of their components
  • cross_statement — Balance Sheet equity ties to Statement of Changes in Equity closing balance; P&L PAT ties to retained-earnings movement
  • mandatory — required elements present (e.g. sg-dei_NameOfCompany)
  • sign_conventionbalance = credit elements appear as credits
  • formatmonetaryItemType uses Decimal(20,2) precision, dates are ISO

Micro-Steps

  1. Open the Validation tab. Click Run validation.
  2. The handler enqueues run-xbrl-validation:
    • Loads all confirmed mappings + the pinned taxonomy + the rules for that version
    • Evaluates every rule's expression against the line-item values
    • Writes one XbrlValidationResult per rule (some passing, some failing) keyed (xbrlFilingId, ruleId)
  3. The UI refreshes into three panes: Errors / Warnings / Info. Each row shows the rule id, message, and relatedElements.
  4. Filing transitions:
    • VALIDATION_PASSED if no row has severity = ERROR AND passed = false
    • VALIDATION_FAILED otherwise

Decision Points and Branching Logic

  • IF VALIDATION_FAILED, THEN the preparer revisits mappings, fixes, and re-runs. There is no override.
  • IF VALIDATION_PASSED, the filing is exportable only if every mapping is also confirmed — the export gate re-checks both rules at export time.

System Interaction

  • System: API (POST /ops/xbrl/filings/:id/validate), worker (run-xbrl-validation), constitution loaders.

Data Storage and Evidence

  • XbrlValidationResult rows.
  • AuditEvent xbrl.validation.run with rule count, error count, warning count.

Common Mistakes to Avoid

  • Do not assume a WARNING-severity row is exempt. Warnings do not block export, but ACRA can reject for warning-only issues during filing.
  • Do not edit a line-item value directly to "make the rule pass". If a totalling rule fails, the inputs are wrong — fix at source.

Acceptance Criteria

  • [ ] XbrlValidationResult rows present
  • [ ] Filing is VALIDATION_PASSED (or VALIDATION_FAILED with a clear remediation plan)

Step 5.0: Export BizFinx XLSX / XBRL XML (VALIDATION_PASSED → EXPORTED)

Process Phase: EXPORT

Actor: XBRL Reviewer / Platform Admin (or Senior Accountant)

Action Description

Render the BizFinx Excel workbook and/or the XBRL XML instance document. Both go through the same export gate.

The Export Gate (assertExportAllowed)

Before any byte of output is produced, packages/xbrl/src/export-gate.ts is called. It throws XbrlExportBlockedError(reason) for any of:

ReasonCondition
NO_LINE_ITEMSThe filing has no XbrlLineItem rows
NO_VALIDATION_RUNNo XbrlValidationResult rows exist (validation hasn't been run)
VALIDATION_ERROR_PRESENTAt least one XbrlValidationResult row has severity = ERROR AND passed = false
UNCONFIRMED_TAG_MAPPINGAt least one XbrlTagMapping.confirmedById IS NULL

WARNING-severity failures do not block export — they surface in the UI and on the filing log for human judgment, but they do not gate.

The API translates XbrlExportBlockedError to HTTP 422 with the typed reason. Worker handlers re-check the gate (defence in depth).

BizFinx XLSX layout (multi-sheet)

SheetSource elements
Income Statementperiod_type = duration, P&L section
Balance Sheetperiod_type = instant, SOFP section
Cash Flowperiod_type = duration, SOCF section
Equity ChangesSOCE section
Filing Informationsg-dei_* elements (name, UEN, period, entry point)

XBRL XML layout

  • <xbrl> root with namespace declarations for the pinned taxonomy version
  • One <context> per (period, entity) combination — <instant> for balance-sheet elements, <startDate>/<endDate> for flow elements
  • One <unit> for SGD (<measure>iso4217:SGD</measure>)
  • One <element> fact per confirmed mapping with contextRef + unitRef

Micro-Steps

  1. Open the Exports tab. Two buttons: Generate BizFinx and Generate XBRL XML.
  2. Click one. The handler enqueues generate-bizfinx-xlsx or generate-xbrl-xml.
  3. Handler re-checks the gate; on failure, no artifact is produced and the UI shows the typed reason with the offending line items / rule ids.
  4. On pass:
    • Build the workbook / XML
    • Persist via the File model with key prefix xbrl/<clientId>/<filingId>/<artifact>-v<n>.{xlsx,xml}
    • Insert XbrlOutputArtifact row with kind, versionNo, signed URL
  5. Filing transitions VALIDATION_PASSED → EXPORTED (first time only).

Data Storage and Evidence

  • XbrlOutputArtifact rows — every version preserved (multiple exports allowed; each is a new artifact).
  • AuditEvent xbrl.export.generated with kind and versionNo.

Acceptance Criteria

  • [ ] At least one XbrlOutputArtifact row exists for the filing
  • [ ] Filing is EXPORTED
  • [ ] Signed URL returned to the staff user

Step 6.0: Client Sign-off via Portal (Optional, EXPORTED)

Process Phase: REVIEW

Actor: Client Approver

Action Description

Optionally send the filing to the client for sign-off before submission to ACRA. The portal renders a filing summary (UEN, period, entry point), statement-level previews, and the validation-passed status; the client confirms the UEN and approves, or requests revision.

Micro-Steps

  1. Staff clicks Send to client for sign-off. Handler creates a PortalInvitation with resourceType = XBRL_FILING, token.product = XBRL_FILING.
  2. Email sent: subject "XBRL filing ready for sign-off", body links to /portal/<token>.
  3. The portal verifies the token, loads the filing summary + previews, and shows:
    • UEN confirmation field (must echo the captured xbrlConfig.uen)
    • Approve — captures decision, audits, notifies staff
    • Request revision — captures comment, audits, notifies staff
  4. On revision request, staff back-routes the filing to MAPPING_IN_PROGRESS and addresses the comment.

Acceptance Criteria

  • [ ] Client decision captured with timestamp and (if any) comment
  • [ ] AuditEvent xbrl.client.approved or xbrl.client.revision_requested

Step 7.0: Mark Filed (EXPORTED → FILED)

Process Phase: FILE

Actor: XBRL Reviewer or Platform Admin only (MARK_XBRL_FILED)

Action Description

After uploading the BizFinx workbook through ACRA's BizFinx Preparation Tool (or submitting the XBRL XML directly) and receiving an ACRA acknowledgement, record the filing reference and the filed-at timestamp against the filing.

Why MARK_XBRL_FILED is restricted

EXPORTED → FILED is the regulator-facing acknowledgement. The boundary deliberately matches human accountability: whoever marks the filing is the one taking responsibility with ACRA. Even Senior Accountants who can do everything else short of filing cannot do this.

Micro-Steps

  1. Open the filing detail. Click Mark filed.
  2. Provide the ACRA filing reference (received from the BizFinx Preparation Tool).
  3. Filing transitions EXPORTED → FILED. filedAt and filedById are set. Sealed for editing.

Acceptance Criteria

  • [ ] XbrlFiling.status = FILED
  • [ ] ACRA filing reference captured
  • [ ] AuditEvent xbrl.filing.marked_filed

Step 8.0: Archive (FILED → ARCHIVED)

Process Phase: ARCHIVE

Actor: XBRL Reviewer / Platform Admin

Action Description

Seal the filing.

Acceptance Criteria

  • [ ] Filing reaches ARCHIVED
  • [ ] AuditEvent xbrl.filing.archived

7. System Architecture for AI Implementation

Process Input Schema (High Level)

Field NameData TypeValidation RulesRequired/OptionalSource System
clientIdUUIDXBRL_FILING in enabledProductsRequiredClient master
periodStart / EndYYYY-MM-DDStart < EndRequiredFiling create
entryPointEnumOne of 4 entry-point valuesRequiredFiling create
entityTypeEnumOne of 5 entity-type valuesRequiredFiling create
taxonomyVersionStringMust exist in packages/xbrl/constitution/RequiredFiling create (immutable)
Source DOCX/PDFFileMax ~10 MB; textual tables (not scanned raster)Required (or FS link)Document upload
elementId per lineStringMember of pinned taxonomyRequired after mappingMapping confirmation
confirmedByIdUUIDAuthenticated staff userRequired for exportMapping confirmation

Process Output Schema (High Level)

OutputData TypeFormat SpecificationDestinationRetention
BizFinx workbookXLSXMulti-sheet ACRA-shaped workbookS3 + signed URLPer policy
XBRL XMLXMLXBRL instance with contexts/unitsS3 + signed URLPer policy
Validation resultsJSONB rowsXbrlValidationResultDBPer policy
Mapping decisionsDB rowsXbrlTagMappingDBPer policy
Audit eventsAppend-onlyAuditEvent rowsDBImmutable

Integration Points

IntegrationProtocolDirectionError Handling
S3 (source, output)S3 clientIn/OutboundStandard SDK retry; SHA-256 checksum on download
BizFinx Preparation ToolManual uploadOutboundOut-of-band: staff uploads the XLSX manually; ACRA reference captured on filing
ACRA (XBRL XML submission)Manual submission (Phase 2); arelle-validated XML (Phase 4)OutboundACRA acknowledgement captured manually on Mark Filed
Email (client portal)SMTP adapterOutboundOutbox-poller with retry; manual reissue path

Constitution & Loader Contract

  • loadTaxonomy(version) — versioned loader; throws XbrlUnknownTaxonomyVersionError for unknown versions. Currently knows: acra_2026_v1.
  • TaxonomyLookup — element queries (by id, by entry point, by section). The only permitted entry point for element access — Rule 1.
  • loadValidationRules(version) — returns the 144 rules for the pinned version.
  • rulesForEntryPoint(version, entryPoint) — filtered subset (e.g. ~100+ for FULL_XBRL).
  • exactMatch(label) — case-insensitive lookup in the synonym library; returns {target_element_id, confidence} or undefined.
  • appendSynonym({label, elementId, staffUserId}) — writes to mapping_library.json; emits audit event; restricted to ADD_MAPPING_SYNONYM.
  • assertExportAllowed(input) — the gate. See Step 5.0 above.

8. Quality Controls and Compliance Checkpoints

CheckpointWhat to CheckWho ChecksFrequencyRecord
Source document parsedXbrlSourceDocument.parseStatus = PARSEDXFE, PreparerPer uploadDB row
Mapping completenessEvery XbrlLineItem has a confirmedById != NULL mappingXFE, ReviewerPre-validationDB rows
Validation runXbrlValidationResult rows exist for the filing's pinned taxonomy versionXFE, ReviewerPre-exportDB rows
Export gate (Rule 2)No ERROR-severity unpassed validation rowGate (code)Per export attemptHTTP 422 if blocked
Export gate (Rule 3)No unconfirmed mappingGate (code)Per export attemptHTTP 422 if blocked
Taxonomy literal check (Rule 1)No sg-as_, sg-dei_, sg-bp_, sg-fs_ literals in packages/xbrl/src/ outside taxonomy/Automated testEvery test runTest fail if violated
Unknown taxonomy version refused (Rule 4)loadTaxonomy('made_up') throws XbrlUnknownTaxonomyVersionErrorAutomated testEvery test runTest fail if violated
Regression suite (Rule 5)pnpm --filter @breezycorp/xbrl test greenCIEvery PRCI run
Synonym write auditedEvery mapping_library.json write has matching AuditEvent xbrl.mapping.synonym_addedReviewer / SAPer writeAuditEvent
ACRA filing reference capturedMark Filed recorded the regulator-assigned referenceReviewerPer filingXbrlFiling row

  • ACRA Taxonomy 2026 v1.0 (1871 elements) — source-of-truth at xbrl-saas/infrastructure/scripts/ACRA Taxonomy in Excel_2026_v1.0.xlsx (converted to JSON via taxonomy_excel_to_json.py).
  • ACRA Business Rules 2026 v1.0 (144 rules) — source at xbrl-saas/infrastructure/scripts/validationbusinessrules2026v1.xlsx (converted via rules_excel_to_json.py).
  • BizFinx Preparation Tool (ACRA) — accepts the multi-sheet XLSX produced by Step 5.0.
  • Companies Act 1967 — XBRL filing obligation alongside annual returns.
  • PDPA — UEN and directors' personal data treated as regulated PII.

10. Records Management and Retention

Records to store for each filing

  • Source DOCX/PDF — S3
  • XbrlSourceDocument rows (sha256, parse status, page count)
  • XbrlLineItem rows (immutable after extraction; re-uploading replaces the source doc)
  • XbrlTagMapping rows with confirm/unconfirm history (the confirmedById and confirmedAt field updates capture changes; AuditEvent rows preserve the audit trail)
  • XbrlValidationResult rows (every run preserved)
  • XbrlOutputArtifact rows — every export version
  • ACRA filing reference (on Mark Filed)
  • Client portal sign-off evidence (if used)
  • AuditEvent rows — append-only

Retention

Minimum 7 years from the filing year, consistent with Singapore accountancy norms and ACRA expectations.


11. Risk Assessment and Mitigation

Risk DescriptionLikelihood (1-5)Impact (1-5)Risk ScoreCategory
Wrong taxonomy element mapped to a line item (incorrect filing accepted by ACRA)2510Regulatory
Filing exported with an unconfirmed mapping (cursorrules Rule 3 violated)155Regulatory / Compliance
Filing exported with an ERROR-severity validation rule failing (Rule 2 violated)155Regulatory / Compliance
Synonym library polluted by a wrong save-as-synonym; affects future filings across all clients248Multi-tenant
Taxonomy literal slipped into application code outside the loader (Rule 1 violated)144Engineering
MARK_XBRL_FILED used by an unauthorised role144RBAC
Source document parser produces noisy line items (PDFs with merged cells, OCR'd content)339Operational

Preventive Controls

  • Export gate runs at the service layer AND in worker handlers — defence in depth, no way for a future code path to bypass.
  • Automated test __tests__/no-element-literals.test.ts greps packages/xbrl/src/ for ACRA element prefixes and fails the build on any new literal.
  • MARK_XBRL_FILED checked at the RBAC layer; only XBRL_REVIEWER + PLATFORM_ADMIN permitted.
  • ADD_MAPPING_SYNONYM is restricted; every write is audited. The Phase 4 backlog includes per-client override files to limit cross-client blast radius.
  • Pinned taxonomyVersion is immutable; ACRA taxonomy upgrades land as new constitution files and a separate filing-version migration path.

Escalation

  • A VALIDATION_FAILED filing that cannot be repaired through three mapping iterations escalates to Senior Accountant; the export gate output (reason, details) is the input to the diagnostic.
  • A synonym write that turns out to be wrong: the offending row in mapping_library.json is reverted via PR; downstream filings that used the bad synonym are flagged for re-mapping. The AuditEvent trail identifies them.
  • ACRA rejection after FILED: capture the rejection reason; back-route the filing to MAPPING_IN_PROGRESS (allowed from EXPORTED); fix and re-export.

12. Process Re-engineering and Continual Improvement

  • Quarterly review of the suggestion engine's hit rate. A drop in HIGH confidence indicates either the synonym library is stale or new client document formats are entering the pipeline.
  • After every ACRA taxonomy release: port the new Excel files to JSON via the conversion scripts; add the new versioned constitution file; bump the loadTaxonomy() accepted-version list; the prior version remains supported for in-flight filings.
  • Track validation-rule false-positive rates. Rules that fail on legitimate filings need an upstream conversation with ACRA or a documented carve-out.
  • Track arelle validation results (Phase 4) against rule outcomes; the two should agree.

13. Training and Competency Requirements

Minimum Competency Standards

  • Understanding of the ACRA taxonomy categories (statement-of-financial-position elements, profit-and-loss elements, disclosure elements, document/entity-information elements).
  • Familiarity with period_type (instant vs duration) and balance (debit vs credit) semantics.
  • Ability to read a validation rule message and trace it back to the offending element.
  • Understanding that the export gate has no override path. The right answer to "I need to export anyway" is "fix the mapping or the rule failure".

Training Program

  • New XBRL Preparers shadow two complete filings end-to-end before independent ownership.
  • XBRL Reviewers spend one cycle pairing with a Senior Accountant on a VALIDATION_FAILED recovery.
  • Annual refresher on ACRA taxonomy updates and Business Rules changes.


15. Appendices

Appendix A: Process Flow (Swimlane Description)

  • XBRL Preparer creates the filing with pinned taxonomy version.
  • XFE ingests the source DOCX/PDF: parses tables, normalises amounts, persists XbrlLineItem rows.
  • XFE runs suggest-tag-mappings: exact-match against mapping_library.json, fuzzy-match against taxonomy element labels.
  • XBRL Preparer walks every line item and confirms the mapping (or picks an alternative / searches / saves a new synonym).
  • XBRL Reviewer (or Senior Accountant) runs validation.
  • On VALIDATION_FAILED, return to mapping; iterate.
  • On VALIDATION_PASSED, XBRL Reviewer exports BizFinx XLSX and/or XBRL XML. Export gate re-checks both rules.
  • Optional: portal sign-off by client approver.
  • XBRL Reviewer (or Platform Admin) uploads BizFinx XLSX to ACRA; captures filing reference; clicks Mark filed.
  • Filing archived after the audit cycle closes.

Appendix B: Worked Example (Fictional Data — STELLAR)

ClientCode: STELLAR (seeded as an XBRL-only client)

Filing 1: STELLAR / period 2024-01-01 → 2024-12-31, FULL_XBRL, acra_2026_v1, SFRS.

  • Source DOCX uploaded; 5 line items extracted across balance_sheet and income_statement.
  • Mappings: 3 confirmed by senior@spade.local (Total Assets, Total Liabilities, Total Equity); 2 unconfirmed (Revenue, Profit Before Tax).
  • Export gate refuses with UNCONFIRMED_TAG_MAPPING (details lists the two unconfirmed line items).

Filing 2: STELLAR / period 2023-01-01 → 2023-12-31, same entry point + standard.

  • All 5 mappings confirmed.
  • Validation run: 1 ERROR (BR_totalling_001 — equity does not balance), 1 WARNING (BR_arithmetical_005), 1 INFO (passed).
  • Export gate refuses with VALIDATION_ERROR_PRESENT.
  • Recovery: preparer revisits the equity mapping; fixes the offending line item value at the source document; re-runs validation; on pass, exports BizFinx XLSX and XBRL XML.

Appendix C: Junior Staff Decision Guide

If You See This...Then Do This...Escalate?
Suggestion has LOW confidenceOpen the line item; check the source page reference; pick from alternatives[] or search the taxonomyYes if pattern recurs
Export gate raises UNCONFIRMED_TAG_MAPPINGOpen the mappings tab; filter for unconfirmed rows; confirm each oneNo
Export gate raises VALIDATION_ERROR_PRESENTOpen the failing rule message; trace relatedElements back to the offending line items; fix at sourceYes if recurring rule
Source PDF yielded zero line itemsThe PDF was probably rasterised. Ask the client for a DOCX or a text-extractable PDF, or use the cross-product from-fs-engagement pathYes to SA
Save-as-synonym button is disabledYou do not hold ADD_MAPPING_SYNONYM — escalate to Reviewer or Senior AccountantNo
Mark Filed button is disabledOnly XBRL_REVIEWER or PLATFORM_ADMIN may mark filedNo

Appendix D: Escalation Matrix

  • Preparer to Reviewer: any LOW-confidence mapping where alternatives all seem wrong; validation rule failing on what looks like correct data.
  • Reviewer to Senior Accountant: persistent validation failure across multiple iterations; cross-product hand-off questions when fsEngagementId is set.
  • Senior Accountant to Managing Director: ACRA rejection post-filing; suspected taxonomy bug affecting multiple clients.

Appendix E: Completion Checklist

  • [ ] Filing created in DRAFT with pinned taxonomy version
  • [ ] Source document uploaded; filing reached MAPPING_IN_PROGRESS
  • [ ] Every XbrlLineItem has a confirmed XbrlTagMapping
  • [ ] Validation run; filing reached VALIDATION_PASSED
  • [ ] At least one XbrlOutputArtifact exists; filing reached EXPORTED
  • [ ] Optional: client portal sign-off captured
  • [ ] BizFinx workbook uploaded to ACRA; filing reference captured; filing reached FILED
  • [ ] Filing archived; retention applied

End of SOP

Internal use only — BreezyCorp