XBRL Filing (ACRA)
1. Document Control
| Document Title | Singapore ACRA XBRL Filing Automation |
|---|---|
| Document ID | SOP-ACC-004 |
| Version | 1.0 (Draft for Automation Build) |
| Effective Date | [Insert Date] |
| Review Date | [Insert Date + 12 months] |
| Document Owner | Head of Regulatory Filings |
| Approver | Managing Director |
| Status | Draft |
Version History
| Version | Date | Author | Changes | Approved By |
|---|---|---|---|---|
| 1.0 | [Insert Date] | [Insert Author] | Initial SOP for the AI-assisted XBRL filing module (BreezyCorp Phase 2) | [Insert Approver] |
Distribution
| Role Title | Access Rights |
|---|---|
| Client Approver | Read-only |
| XBRL Preparer | Edit |
| XBRL Reviewer | Edit |
| Senior Accountant | Edit (no Mark Filed) |
| Platform Admin | Edit |
| Quality Reviewer | Read-only |
| AI Workflow Developer | Read-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)
2B. Applicable Legal Framework and Statutory Authority
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 variants —
FULL_XBRL,SIMPLIFIED_XBRL,FSH_BANKS,FSH_INSURANCE. Pinned per filing at creation. - Entity type —
NON_LISTED_COMPANY_FULL,SMALLER_NON_LISTED_COMPANY,SGX_LISTED,MAS_LICENSED_BANK,MAS_LICENSED_INSURER. - Accounting standard —
SFRS,SFRS_SE,IFRS.
Compliance Horizon
This SOP is designed so that no XBRL output leaves the system without:
- Every tag mapping confirmed by an authenticated staff user.
- 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/Abbreviation | Definition |
|---|---|
| XFE | XBRL Filing Engine — the automation layer that orchestrates ingestion, mapping, validation, export |
| ACRA | Accounting and Corporate Regulatory Authority (Singapore) |
| BizFinx | ACRA's filing preparation tool; accepts a multi-sheet Excel workbook for upload |
| XBRL | eXtensible Business Reporting Language — standardised tagging format for financial data |
| Entry Point | An ACRA taxonomy variant: FULL_XBRL (default for non-listed companies), SIMPLIFIED_XBRL, FSH_BANKS, FSH_INSURANCE |
| Entity Type | Filing category: non-listed full, smaller non-listed, SGX-listed, MAS-licensed bank, MAS-licensed insurer |
| Element | A single taxonomy concept (e.g. sg-as_TotalAssets). Each carries data_type, period_type (instant / duration), balance (debit / credit) |
| Line Item | One extracted monetary or string fact from the source document, awaiting tag mapping |
| Tag Mapping | The decision that a given line item maps to a given element — requires human confirmation |
| Constitution | Immutable JSON in packages/xbrl/constitution/: taxonomy_acra_2026_v1.json, validation_rules_acra_2026_v1.json, mapping_library.json |
| Synonym Library | mapping_library.json — fuzzy-match seed of label → element_id pairs. Writable at runtime; every write is audited |
| UEN | Unique Entity Number — Singapore company identifier |
| AL | Audit Logger — AuditEvent rows with actor, action, payload, timestamp |
| Export Gate | assertExportAllowed() in packages/xbrl/src/export-gate.ts. Throws XbrlExportBlockedError (HTTP 422) on rule 2 or 3 failure |
4. Roles and Responsibilities
| Role | Responsibilities | Competency Requirements |
|---|---|---|
| XBRL Preparer | Create filing; ingest DOCX/PDF or pull from FS engagement; confirm or override every tag mapping suggestion | ACRA taxonomy familiarity; willingness to refuse a fuzzy match that doesn't fit |
| XBRL Reviewer | All preparer rights + run validation; export BizFinx XLSX / XBRL XML; mark filed; add new synonyms to the mapping library | Senior XBRL judgment; understanding that synonym writes affect future filings for every client |
| Senior Accountant | All XBRL Preparer + XBRL Reviewer rights except MARK_XBRL_FILED — reserved for XBRL_REVIEWER / PLATFORM_ADMIN | Cross-product judgment (FS + XBRL) |
| Client Approver | Review the filing summary + statement-level previews via the portal magic link; Approve or Request Revision before submission | Familiarity 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 gate | Constitution 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_FILEDis restricted toXBRL_REVIEWERandPLATFORM_ADMIN. EvenSENIOR_ACCOUNTANTcannot mark a filing as accepted by ACRA. The boundary intentionally matches human accountability with the regulator.ADD_MAPPING_SYNONYMis restricted toXBRL_REVIEWER,SENIOR_ACCOUNTANT,PLATFORM_ADMIN. Each synonym write isAuditEvent-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
confirmedByIdautomatically.
5. Prerequisites and Entry Conditions
Before commencing this process, verify the following conditions are met:
- Client master record exists with
XBRL_FILINGinenabledProducts. Client.xbrlConfigis populated withentityType,defaultEntryPoint,taxonomyVersion(e.g.acra_2026_v1),accountingStandard, anduen.- Staff users hold the appropriate role:
XBRL_PREPARERto drive the filing through to validation;XBRL_REVIEWERto export and mark filed. - The source document for ingestion exists — either a financial-statement DOCX/PDF, or a
FsGeneratedStatementin aFINANCIAL_STATEMENTSengagement 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_XBRLtypical 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)
- CREATE — Filing creation with pinned taxonomy version
- INGEST — Source document upload → line-item extraction
- MAP — Per-line-item element confirmation (fuzzy-match suggested; human-confirmed)
- VALIDATE — Run the 144 ACRA business rules
- EXPORT — BizFinx XLSX or XBRL XML (gated on Rule 2 + Rule 3)
- REVIEW — Optional client portal sign-off
- FILE — Mark filed against ACRA submission reference
- 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.
- No taxonomy literal outside constitution + loader. All element references flow through
TaxonomyLookup. Asserted by__tests__/no-element-literals.test.tswhich grepspackages/xbrl/src/for ACRA element prefixes. - No XBRL output without passing validation.
assertExportAllowed()raisesVALIDATION_ERROR_PRESENT(HTTP 422) if anyXbrlValidationResultrow hasseverity = ERRORANDpassed = false. - Every tag mapping must be human-confirmed. Same gate raises
UNCONFIRMED_TAG_MAPPINGif anyXbrlTagMapping.confirmedById IS NULL. No code path auto-confirms. - Taxonomy version is first-class.
loadTaxonomy(version)throwsXbrlUnknownTaxonomyVersionErrorfor unknown versions.XbrlFiling.taxonomyVersionis required at create and immutable thereafter. - Run the regression suite before push.
pnpm --filter @breezycorp/xbrl testincludes 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 Name | Format | Source | Validation Rule |
|---|---|---|---|
clientId | UUID | Client master | Must have XBRL_FILING enabled |
periodStart | YYYY-MM-DD | User input | < periodEnd |
periodEnd | YYYY-MM-DD | User input | > periodStart |
entryPoint | Enum | xbrlConfig default | One of FULL_XBRL / SIMPLIFIED_XBRL / FSH_BANKS / FSH_INSURANCE |
entityType | Enum | xbrlConfig default | One of the 5 entity types |
accountingStandard | Enum | xbrlConfig default | SFRS / SFRS_SE / IFRS |
taxonomyVersion | String | xbrlConfig default | Must exist in packages/xbrl/constitution/ |
fsEngagementId | UUID (nullable) | Optional cross-link | Same clientId; must exist |
Micro-Steps
- Open
/dashboard/xbrl/new(orPOST /ops/xbrl/filings). - Fill in header. Dropdowns default from
Client.xbrlConfig. - Submit. Filing created in
DRAFT.taxonomyVersionis now immutable.
Validation and Control Checks
- Check 1: Caller holds
MANAGE_XBRL_FILING. - Check 2:
taxonomyVersionis loadable (loadTaxonomy(version)does not throw). If unknown →400. - Check 3: No duplicate
(clientId, periodEnd, taxonomyVersion)filing exists.
Decision Points and Branching Logic
- IF
enabledProductsdoes not includeXBRL_FILING, THEN request rejected with400. - IF an
fsEngagementIdis 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
XbrlFilingrow, emitAuditEventxbrl.filing.created
Data Storage and Evidence
XbrlFilingrow withversionNo = 1,status = DRAFT,taxonomyVersionpinned.
Acceptance Criteria
- [ ] Filing created in
DRAFT - [ ] Audit log shows
xbrl.filing.createdwith pinnedtaxonomyVersion
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
| Input | Format | Notes |
|---|---|---|
| Source document | DOCX / PDF | Max ~10 MB |
| Statement type | Inferred | balance_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
- Open the filing; click Upload source document.
- Drag-drop the DOCX or PDF. Multipart upload to
POST /ops/xbrl/filings/:id/documents. - The handler:
- Persists the bytes via the
Filemodel with key prefixxbrl/<clientId>/<filingId>/source.{docx,pdf} - Computes SHA-256
- Inserts
XbrlSourceDocumentwithparseStatus = PENDING - Enqueues
extract-line-items
- Persists the bytes via the
extract-line-items:- Reads the file from S3
- Parses tables and text; normalises numbers (strip commas, parentheses → negative, currency symbols)
- Inserts
XbrlLineItemrows:{statement, label, valueCurrent, valuePrior, sourcePage, sourceLine} - Updates
XbrlSourceDocument.parseStatus = PARSED(orFAILED) - Transitions filing
DRAFT → DOCUMENTS_INGESTED - Enqueues
suggest-tag-mappings
suggest-tag-mappings:- Iterates every
XbrlLineItemwithout a confirmed mapping - Exact-match against
mapping_library.jsonsynonyms (case-insensitive) - On miss, fuzzy-match against taxonomy element labels filtered by
applicable_entry_pointsandtaxonomy_section - Persists
XbrlTagMappingwithconfirmedById = NULL,alternativespopulated (top-N candidates for the UI) - Transitions filing
DOCUMENTS_INGESTED → MAPPING_IN_PROGRESS
- Iterates every
Validation and Control Checks
- Check 1: SHA-256 deduplication — re-uploading the same file is idempotent.
- Check 2:
parseStatus = PARSEDbefore 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 = FAILEDand the filing stays atDRAFT. Reviewer either fixes the source file or, in the cross-product path, switches tofrom-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
XbrlSourceDocumentrow with sha256, parse status, page count.XbrlLineItemrows.XbrlTagMappingrows (unconfirmed) withalternativesfor the UI.AuditEventxbrl.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
XbrlLineItemhas anXbrlTagMapping(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
- Open the Mappings tab. Master-detail layout: line-items list on the left, element-confirmation panel on the right.
- 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)
- Confirm or override:
- Confirm — accepts the current suggestion; sets
confirmedByIdandconfirmedAt. - Pick alternative — sets
elementIdto the chosen alternative; confirms. - Search and pick — searches the taxonomy; sets
elementId; confirms. - "Save as synonym" — additionally appends
{label, elementId}tomapping_library.json. RequiresADD_MAPPING_SYNONYMpermission. Each write is audited.
- Confirm — accepts the current suggestion; sets
- To unconfirm a row, click the unconfirm button.
confirmedByIdandconfirmedAtclear. The export gate will block until re-confirmed.
Validation and Control Checks
- Check 1:
elementIdmust exist in the pinned taxonomy version. UI dropdown is constrained. - Check 2:
confirmedByIdis set to an authenticated staff user. No background job is permitted to set this. - Check 3: Save-as-synonym requires the higher
ADD_MAPPING_SYNONYMaction.
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.jsonhas a high-confidence existing synonym for the label, the suggestion isHIGHand one confirmation closes the row.
System Interaction
- System: API (
POST /ops/xbrl/filings/:id/mappings/:lineItemId,DELETEsame), worker (none — synchronous), constitution.
Data Storage and Evidence
XbrlTagMappingrow withelementId,confidence,alternatives,explanation,confirmedById,confirmedAt.AuditEventxbrl.mapping.confirmedper row.AuditEventxbrl.mapping.synonym_added(also) when save-as-synonym fires.
Acceptance Criteria
- [ ] Every
XbrlLineItemhas anXbrlTagMappingwithconfirmedById != 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_convention —
balance = creditelements appear as credits - format —
monetaryItemTypeusesDecimal(20,2)precision, dates are ISO
Micro-Steps
- Open the Validation tab. Click Run validation.
- The handler enqueues
run-xbrl-validation:- Loads all confirmed mappings + the pinned taxonomy + the rules for that version
- Evaluates every rule's
expressionagainst the line-item values - Writes one
XbrlValidationResultper rule (some passing, some failing) keyed(xbrlFilingId, ruleId)
- The UI refreshes into three panes: Errors / Warnings / Info. Each row shows the rule id, message, and
relatedElements. - Filing transitions:
VALIDATION_PASSEDif no row hasseverity = ERROR AND passed = falseVALIDATION_FAILEDotherwise
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
XbrlValidationResultrows.AuditEventxbrl.validation.runwith 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
- [ ]
XbrlValidationResultrows present - [ ] Filing is
VALIDATION_PASSED(orVALIDATION_FAILEDwith 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:
| Reason | Condition |
|---|---|
NO_LINE_ITEMS | The filing has no XbrlLineItem rows |
NO_VALIDATION_RUN | No XbrlValidationResult rows exist (validation hasn't been run) |
VALIDATION_ERROR_PRESENT | At least one XbrlValidationResult row has severity = ERROR AND passed = false |
UNCONFIRMED_TAG_MAPPING | At 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)
| Sheet | Source elements |
|---|---|
| Income Statement | period_type = duration, P&L section |
| Balance Sheet | period_type = instant, SOFP section |
| Cash Flow | period_type = duration, SOCF section |
| Equity Changes | SOCE section |
| Filing Information | sg-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 withcontextRef+unitRef
Micro-Steps
- Open the Exports tab. Two buttons: Generate BizFinx and Generate XBRL XML.
- Click one. The handler enqueues
generate-bizfinx-xlsxorgenerate-xbrl-xml. - Handler re-checks the gate; on failure, no artifact is produced and the UI shows the typed
reasonwith the offending line items / rule ids. - On pass:
- Build the workbook / XML
- Persist via the
Filemodel with key prefixxbrl/<clientId>/<filingId>/<artifact>-v<n>.{xlsx,xml} - Insert
XbrlOutputArtifactrow withkind,versionNo, signed URL
- Filing transitions
VALIDATION_PASSED → EXPORTED(first time only).
Data Storage and Evidence
XbrlOutputArtifactrows — every version preserved (multiple exports allowed; each is a new artifact).AuditEventxbrl.export.generatedwithkindandversionNo.
Acceptance Criteria
- [ ] At least one
XbrlOutputArtifactrow 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
- Staff clicks Send to client for sign-off. Handler creates a
PortalInvitationwithresourceType = XBRL_FILING,token.product = XBRL_FILING. - Email sent: subject "XBRL filing ready for sign-off", body links to
/portal/<token>. - 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
- UEN confirmation field (must echo the captured
- On revision request, staff back-routes the filing to
MAPPING_IN_PROGRESSand addresses the comment.
Acceptance Criteria
- [ ] Client decision captured with timestamp and (if any) comment
- [ ]
AuditEventxbrl.client.approvedorxbrl.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
- Open the filing detail. Click Mark filed.
- Provide the ACRA filing reference (received from the BizFinx Preparation Tool).
- Filing transitions
EXPORTED → FILED.filedAtandfiledByIdare set. Sealed for editing.
Acceptance Criteria
- [ ]
XbrlFiling.status = FILED - [ ] ACRA filing reference captured
- [ ]
AuditEventxbrl.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 - [ ]
AuditEventxbrl.filing.archived
7. System Architecture for AI Implementation
Process Input Schema (High Level)
| Field Name | Data Type | Validation Rules | Required/Optional | Source System |
|---|---|---|---|---|
clientId | UUID | XBRL_FILING in enabledProducts | Required | Client master |
periodStart / End | YYYY-MM-DD | Start < End | Required | Filing create |
entryPoint | Enum | One of 4 entry-point values | Required | Filing create |
entityType | Enum | One of 5 entity-type values | Required | Filing create |
taxonomyVersion | String | Must exist in packages/xbrl/constitution/ | Required | Filing create (immutable) |
| Source DOCX/PDF | File | Max ~10 MB; textual tables (not scanned raster) | Required (or FS link) | Document upload |
elementId per line | String | Member of pinned taxonomy | Required after mapping | Mapping confirmation |
confirmedById | UUID | Authenticated staff user | Required for export | Mapping confirmation |
Process Output Schema (High Level)
| Output | Data Type | Format Specification | Destination | Retention |
|---|---|---|---|---|
| BizFinx workbook | XLSX | Multi-sheet ACRA-shaped workbook | S3 + signed URL | Per policy |
| XBRL XML | XML | XBRL instance with contexts/units | S3 + signed URL | Per policy |
| Validation results | JSONB rows | XbrlValidationResult | DB | Per policy |
| Mapping decisions | DB rows | XbrlTagMapping | DB | Per policy |
| Audit events | Append-only | AuditEvent rows | DB | Immutable |
Integration Points
| Integration | Protocol | Direction | Error Handling |
|---|---|---|---|
| S3 (source, output) | S3 client | In/Outbound | Standard SDK retry; SHA-256 checksum on download |
| BizFinx Preparation Tool | Manual upload | Outbound | Out-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) | Outbound | ACRA acknowledgement captured manually on Mark Filed |
| Email (client portal) | SMTP adapter | Outbound | Outbox-poller with retry; manual reissue path |
Constitution & Loader Contract
loadTaxonomy(version)— versioned loader; throwsXbrlUnknownTaxonomyVersionErrorfor 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+ forFULL_XBRL).exactMatch(label)— case-insensitive lookup in the synonym library; returns{target_element_id, confidence}orundefined.appendSynonym({label, elementId, staffUserId})— writes tomapping_library.json; emits audit event; restricted toADD_MAPPING_SYNONYM.assertExportAllowed(input)— the gate. See Step 5.0 above.
8. Quality Controls and Compliance Checkpoints
| Checkpoint | What to Check | Who Checks | Frequency | Record |
|---|---|---|---|---|
| Source document parsed | XbrlSourceDocument.parseStatus = PARSED | XFE, Preparer | Per upload | DB row |
| Mapping completeness | Every XbrlLineItem has a confirmedById != NULL mapping | XFE, Reviewer | Pre-validation | DB rows |
| Validation run | XbrlValidationResult rows exist for the filing's pinned taxonomy version | XFE, Reviewer | Pre-export | DB rows |
| Export gate (Rule 2) | No ERROR-severity unpassed validation row | Gate (code) | Per export attempt | HTTP 422 if blocked |
| Export gate (Rule 3) | No unconfirmed mapping | Gate (code) | Per export attempt | HTTP 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 test | Every test run | Test fail if violated |
| Unknown taxonomy version refused (Rule 4) | loadTaxonomy('made_up') throws XbrlUnknownTaxonomyVersionError | Automated test | Every test run | Test fail if violated |
| Regression suite (Rule 5) | pnpm --filter @breezycorp/xbrl test green | CI | Every PR | CI run |
| Synonym write audited | Every mapping_library.json write has matching AuditEvent xbrl.mapping.synonym_added | Reviewer / SA | Per write | AuditEvent |
| ACRA filing reference captured | Mark Filed recorded the regulator-assigned reference | Reviewer | Per filing | XbrlFiling row |
9. Regulatory and Legal References
- 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 viataxonomy_excel_to_json.py). - ACRA Business Rules 2026 v1.0 (144 rules) — source at
xbrl-saas/infrastructure/scripts/validationbusinessrules2026v1.xlsx(converted viarules_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
XbrlSourceDocumentrows (sha256, parse status, page count)XbrlLineItemrows (immutable after extraction; re-uploading replaces the source doc)XbrlTagMappingrows with confirm/unconfirm history (theconfirmedByIdandconfirmedAtfield updates capture changes;AuditEventrows preserve the audit trail)XbrlValidationResultrows (every run preserved)XbrlOutputArtifactrows — every export version- ACRA filing reference (on
Mark Filed) - Client portal sign-off evidence (if used)
AuditEventrows — append-only
Retention
Minimum 7 years from the filing year, consistent with Singapore accountancy norms and ACRA expectations.
11. Risk Assessment and Mitigation
| Risk Description | Likelihood (1-5) | Impact (1-5) | Risk Score | Category |
|---|---|---|---|---|
| Wrong taxonomy element mapped to a line item (incorrect filing accepted by ACRA) | 2 | 5 | 10 | Regulatory |
| Filing exported with an unconfirmed mapping (cursorrules Rule 3 violated) | 1 | 5 | 5 | Regulatory / Compliance |
Filing exported with an ERROR-severity validation rule failing (Rule 2 violated) | 1 | 5 | 5 | Regulatory / Compliance |
| Synonym library polluted by a wrong save-as-synonym; affects future filings across all clients | 2 | 4 | 8 | Multi-tenant |
| Taxonomy literal slipped into application code outside the loader (Rule 1 violated) | 1 | 4 | 4 | Engineering |
MARK_XBRL_FILED used by an unauthorised role | 1 | 4 | 4 | RBAC |
| Source document parser produces noisy line items (PDFs with merged cells, OCR'd content) | 3 | 3 | 9 | Operational |
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.tsgrepspackages/xbrl/src/for ACRA element prefixes and fails the build on any new literal. MARK_XBRL_FILEDchecked at the RBAC layer; onlyXBRL_REVIEWER+PLATFORM_ADMINpermitted.ADD_MAPPING_SYNONYMis restricted; every write is audited. The Phase 4 backlog includes per-client override files to limit cross-client blast radius.- Pinned
taxonomyVersionis immutable; ACRA taxonomy upgrades land as new constitution files and a separate filing-version migration path.
Escalation
- A
VALIDATION_FAILEDfiling 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.jsonis reverted via PR; downstream filings that used the bad synonym are flagged for re-mapping. TheAuditEventtrail identifies them. - ACRA rejection after
FILED: capture the rejection reason; back-route the filing toMAPPING_IN_PROGRESS(allowed fromEXPORTED); fix and re-export.
12. Process Re-engineering and Continual Improvement
- Quarterly review of the suggestion engine's hit rate. A drop in
HIGHconfidence 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
arellevalidation 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(instantvsduration) andbalance(debitvscredit) 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_FAILEDrecovery. - Annual refresher on ACRA taxonomy updates and Business Rules changes.
14. Related Documents and Cross-References
- Architecture — XBRL & FS integration plan
- Status machine — XBRL filing
- Quick start — XBRL filing
- Userflows — XBRL Filing
- SOP — Financial Statements — the upstream engagement this filing may consume (Phase 3 hand-off)
- RBAC matrix —
XBRL_PREPARER,XBRL_REVIEWER,ADD_MAPPING_SYNONYM,MARK_XBRL_FILED
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
XbrlLineItemrows. - XFE runs
suggest-tag-mappings: exact-match againstmapping_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_sheetandincome_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 confidence | Open the line item; check the source page reference; pick from alternatives[] or search the taxonomy | Yes if pattern recurs |
Export gate raises UNCONFIRMED_TAG_MAPPING | Open the mappings tab; filter for unconfirmed rows; confirm each one | No |
Export gate raises VALIDATION_ERROR_PRESENT | Open the failing rule message; trace relatedElements back to the offending line items; fix at source | Yes if recurring rule |
| Source PDF yielded zero line items | The PDF was probably rasterised. Ask the client for a DOCX or a text-extractable PDF, or use the cross-product from-fs-engagement path | Yes to SA |
| Save-as-synonym button is disabled | You do not hold ADD_MAPPING_SYNONYM — escalate to Reviewer or Senior Accountant | No |
| Mark Filed button is disabled | Only XBRL_REVIEWER or PLATFORM_ADMIN may mark filed | No |
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
fsEngagementIdis set. - Senior Accountant to Managing Director: ACRA rejection post-filing; suspected taxonomy bug affecting multiple clients.
Appendix E: Completion Checklist
- [ ] Filing created in
DRAFTwith pinned taxonomy version - [ ] Source document uploaded; filing reached
MAPPING_IN_PROGRESS - [ ] Every
XbrlLineItemhas a confirmedXbrlTagMapping - [ ] Validation run; filing reached
VALIDATION_PASSED - [ ] At least one
XbrlOutputArtifactexists; filing reachedEXPORTED - [ ] Optional: client portal sign-off captured
- [ ] BizFinx workbook uploaded to ACRA; filing reference captured; filing reached
FILED - [ ] Filing archived; retention applied
End of SOP