From fb0dc5d4447f557d55fc769653ca9124782ba230 Mon Sep 17 00:00:00 2001 From: ChilliGeologist <86278872+ChilliGeologist@users.noreply.github.com> Date: Fri, 11 Sep 2026 11:46:41 +1000 Subject: [PATCH] Establish Australian requirements and dual-database CI baseline --- .github/workflows/lint.yml | 2 + .github/workflows/security.yml | 2 + .github/workflows/tests.yml | 36 +++++++++++++++-- docs/australia/README.md | 46 +++++++++++++++++++++ docs/australia/baseline.md | 73 ++++++++++++++++++++++++++++++++++ docs/australia/code-map.md | 57 ++++++++++++++++++++++++++ docs/australia/requirements.md | 72 +++++++++++++++++++++++++++++++++ 7 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 docs/australia/README.md create mode 100644 docs/australia/baseline.md create mode 100644 docs/australia/code-map.md create mode 100644 docs/australia/requirements.md diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50e1bf8..efb59dc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - australia pull_request: branches: - main + - australia # Least privilege: linting only needs to read the tree. permissions: diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 92da685..d38bc25 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -4,9 +4,11 @@ on: push: branches: - main + - australia pull_request: branches: - main + - australia # Re-run weekly so newly-disclosed CVEs in unchanged dependencies are caught # even without a code change. The run history is SOC 2 (CC7.1) evidence that # we continuously track vulnerabilities. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1a38ced..1c963e7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,9 +4,12 @@ on: push: branches: - main + - australia pull_request: branches: - main + - australia + workflow_dispatch: # Least privilege: the test job only reads the tree. permissions: @@ -16,8 +19,35 @@ jobs: ci: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: php-version: ['8.5'] + database: [sqlite, mysql] + + # Disposable test database only; never use deployment credentials here. + services: + mysql: + image: mysql:8.4 + env: + MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + MYSQL_DATABASE: lineledger_test + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=12 + + env: + APP_ENV: testing + DB_CONNECTION: ${{ matrix.database }} + DB_DATABASE: ${{ matrix.database == 'sqlite' && ':memory:' || 'lineledger_test' }} + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_USERNAME: root + DB_PASSWORD: '' + DB_URL: '' steps: - name: Checkout code @@ -28,6 +58,7 @@ jobs: with: php-version: ${{ matrix.php-version }} tools: composer:v2 + extensions: pdo_mysql, pdo_sqlite coverage: xdebug - name: Setup Node @@ -36,7 +67,7 @@ jobs: node-version: '22' - name: Install Node Dependencies - run: npm i + run: npm ci - name: Run JS Unit Tests run: npm test @@ -54,7 +85,4 @@ jobs: run: npm run build - name: Run Tests - env: - DB_CONNECTION: sqlite - DB_DATABASE: ':memory:' run: ./vendor/bin/pest diff --git a/docs/australia/README.md b/docs/australia/README.md new file mode 100644 index 0000000..060c8f8 --- /dev/null +++ b/docs/australia/README.md @@ -0,0 +1,46 @@ +# Australian support: development status + +Australian support is **not implemented or approved for production use**. +This directory records the fork's implementation evidence and open requirements. +It is not tax advice or an ATO certification. + +## First milestone: baseline and requirements + +- [Code map](code-map.md): verified entry points, risks and existing tests. +- [Requirements register](requirements.md): source-backed specifications and unresolved research. +- [Baseline](baseline.md): reproducible checks, actual results and outstanding gates. + +Keep `main` identical to upstream. Integrate small feature branches into +`australia`. Merge upstream through reviewed sync branches; do not routinely +rebase or force-push the published integration branch. Run the complete suite +on MySQL and SQLite after synchronisation, including Canadian and US tests. +Do not auto-deploy upstream updates to live books. + +## Implementation order + +1. Establish PHP/database baseline, confirm country boundaries and record requirements. +2. Add AU country/defaults and server-side capability restrictions, with CA/US regressions. +3. Add identifiers and effective-dated business registrations. +4. Specify and implement immutable tax facts, precision, GST and invoice output. +5. Implement settlement attribution and auditable BAS/IAS preparation. +6. Validate bank/POS reconciliation, assets, inventory and year-end exports. +7. Implement Australian payroll with specialist-reviewed examples. +8. Add separately authorised STP, super and electronic tax-service integrations. +9. Expand entity, state, award and specialist-industry coverage explicitly. + +Every release needs source-to-test traceability, reviewed expected results, +migration/restore checks and a published capability matrix. Digital-service +authorisation is a separate gate from calculation correctness. + +No upstream contribution is to be submitted without the owner's approval of +the current upstream CLA. Review PRs in this fork do not request upstream review. +Do not commit real business records, TFNs, credentials or payroll data. + +## Next branch acceptance criteria + +`au/country-foundation` must cover every `Country` method, tax-authority catalog, +wizard and model defaults, Australian timezones and July financial-year defaults. +It must not enable Canadian payroll, CRA forms, US 1099 or charity receipts for AU. +Inspect existing `JurisdictionProfile` rather than adding a second capability system. +Resolve the legal-link fallback and onboarding binary country selector explicitly. +The baseline PHP gates must be established before claiming this branch is verified. diff --git a/docs/australia/baseline.md b/docs/australia/baseline.md new file mode 100644 index 0000000..9e38731 --- /dev/null +++ b/docs/australia/baseline.md @@ -0,0 +1,73 @@ +# Baseline evidence + +Inspected 2026-09-11 at upstream commit +`c42d49020e3f65d067e88d5a10765a2b629fbc18`. + +| Check | Observed result | +| --- | --- | +| Initial worktree | Clean on `australia` | +| JavaScript tests (`npm test`) | 60 passed, 0 failed, 0 skipped | +| Local Node | v24.19.0; CI uses Node 22, so this is not an exact CI reproduction | +| PHP, Composer, Docker, MySQL executables | Not available on the inspected workspace PATH | +| PHP/Pest on SQLite | Not run; awaiting CI/runtime | +| PHP/Pest on MySQL | Not run; awaiting CI/runtime | +| Pint / PHPStan | Not run; awaiting CI/runtime | +| Production asset build | Not run; awaiting installed dependencies | +| Dependency / security checks | Not run; awaiting CI | + +The JavaScript result covers the existing arithmetic-input helper, not PHP tax +or payroll calculations. Do not describe the application baseline as passing +until the pending checks have actual successful results attached to a commit. + +## CI changes in this milestone + +The tests, lint and security workflows now include PRs into and pushes to +`australia`, while preserving `main`. Tests use the committed npm lockfile via +`npm ci` and run independent SQLite and MySQL jobs with fail-fast disabled. +MySQL 8.4 is a disposable CI service; its empty password is not a deployment setting. +The service runs in both matrix jobs for configuration simplicity; SQLite uses +`:memory:` and never connects to it. No publish/deploy workflow is changed. + +Only a completed workflow run can demonstrate that these changes work. If a +permission or workflow approval prevents a run, record it and request approval; +do not route around the restriction. Existing failures must be distinguished +from failures introduced by this branch; do not update baselines just to hide them. + +## Reproduce on a development machine + +Use PHP 8.5, Composer 2, Node 22 and the required PHP extensions. Start with a +fresh clone and no production environment or credentials. Install locked dependencies: + +```bash +composer install --no-interaction --prefer-dist --optimize-autoloader +npm ci +``` + +Prepare a development `.env` from `.env.example`, generate an application key, +and use disposable databases only. Do not run `composer run setup` against a +live deployment: that script performs migrations. + +```bash +php artisan key:generate +php artisan config:clear +npm test +npm run build +DB_CONNECTION=sqlite DB_DATABASE=':memory:' DB_URL='' ./vendor/bin/pest +``` + +On a disposable MySQL instance with an empty-password local root account and a +new database named `lineledger_test` (matching the CI service): + +```bash +DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 \ +DB_DATABASE=lineledger_test DB_USERNAME=root DB_PASSWORD='' DB_URL='' ./vendor/bin/pest +vendor/bin/pint --test +vendor/bin/phpstan analyse --no-progress --memory-limit=1G +composer audit --locked --abandoned=report +npm audit --audit-level=high +``` + +Feature tests use `RefreshDatabase` and can destroy test data. Never point these +commands at a business database. Keep overrides explicit so local configuration +does not choose the target. Record commit, runtime versions, database version, +test totals, failures and workflow URL when updating this evidence. diff --git a/docs/australia/code-map.md b/docs/australia/code-map.md new file mode 100644 index 0000000..58abed3 --- /dev/null +++ b/docs/australia/code-map.md @@ -0,0 +1,57 @@ +# Country-specific code map + +Targeted inspection at `c42d49020e3f65d067e88d5a10765a2b629fbc18`. +This is an implementation starting map, not an exhaustive security or route audit. +Paths are repository-relative. Entries marked “trace next” have not been proven end to end. + +| Area | Entry points | Observed behaviour / next action | +| --- | --- | --- | +| Country identity | `app/Enums/Country.php` | CA/US only; explicit matches must all handle AU; `fromHost` treats non-`.ca` hosts as US | +| Company creation | `app/Models/Company.php` | Canada fallback, January financial year, immutable country; timezone options need AU review | +| Seed defaults | `app/Support/Defaults/CompanyDefaults.php`, `CanadianDefaults.php`, `AmericanDefaults.php` | Reusable country contract; add AU implementation without altering old defaults | +| Wizard account templates | `app/Support/Defaults/ChartTemplateBuilder.php` | Separate creation path; Canada-versus-other share terminology needs explicit AU treatment | +| Tax authorities | `app/Support/Tax/TaxAuthorityCatalog.php` | Exhaustive CA/US match requires AU branch; catalog itself does not create an agency | +| Capability boundary | `app/Support/Jurisdiction/JurisdictionProfile.php`, `app/Enums/JurisdictionCapability.php` | Existing single resolver; payroll/Canadian slips share a Canadian predicate; do not broaden the shared arm when later adding AU payroll | +| Entity filing | `app/Support/Tax/FilingProfile.php` | Canadian return eligibility; retain country guard and introduce distinct AU requirements | +| Legal defaults | `app/Support/Legal/LegalDocuments.php`, `config/app.php` | APP_REGION / hostname resolution; missing marketing URL falls back to Canada; must not silently attach Canadian legal framing to AU | +| Navigation and reporting | `app/Support/Navigation/SidebarNavCatalog.php`, `app/Support/Reporting/ReportCatalog.php` | Country-aware display; trace server-side authorisation independently | +| Payroll portal | `app/Http/Middleware/EnsurePortalAudience.php` | References company payroll capability; test direct links and admin overrides for AU | +| MCP profile | `app/Mcp/Tools/CompanyProfileTool.php`, `app/Mcp/Resources/CompanyProfileResource.php` | Descriptions frame filing as CRA; audit data exposure and capability checks | +| MCP tax preparation | `app/Mcp/Prompts/SalesTaxFilingPrepPrompt.php` | Uses country tax label; label changes alone do not implement BAS | +| Tax computation | `app/Services/Posting/TaxCalculator.php`, `app/Models/TaxCode.php` | Existing discount/markup then additive tax; scaled quantity uses float conversion and truncation; characterise before changing rounding | +| Return preparation | `app/Services/Tax/TaxReturnBuilder.php` | Delegates to report tax lines/totals; not a BAS mapping engine | +| Return lifecycle | `app/Services/Tax/TaxReturnFiler.php` | Local frozen snapshot and filed status; no ATO submission; separate accepted-lodgement evidence required | +| Canadian payroll | `app/Services/Payroll/CalculatePayRun.php`, `PayrollDeductionEngine.php` | Canadian CPP/EI/etc.; AU requires its own calculation implementation and classification rules | +| Tax assets | `app/Services/Tax/CcaCalculator.php` | Canadian tax treatment; no AU tax-depreciation claim | +| Persistence | `app/Services/Backup/BackupTableRegistry.php`, `app/Services/Restore/RowTransformer.php` | Explicit registry/transformation paths; all new tables and rule snapshots need round-trip tests | +| Container publishing | `.github/workflows/docker.yml` | Main/release-tag publishing; not an AU release channel; unchanged in this milestone | + +## Existing tests to extend + +- `tests/Feature/Companies/CountryEnumTest.php`: currently asserts exactly two countries. +- `tests/Feature/Companies/CountryImmutabilityTest.php` +- `tests/Feature/Companies/JurisdictionDefaultsTest.php` +- `tests/Feature/Companies/CreateCompanyDefaultsCurrencyTest.php` +- `tests/Feature/Companies/CompanyTimezoneTest.php` +- `tests/Feature/Jurisdiction/JurisdictionCapabilityMatrixTest.php` +- `tests/Unit/ChartTemplateBuilderTest.php` +- `tests/Feature/Accounting/TaxCalculatorTest.php` +- `tests/Feature/Accounting/MultiTaxPostingTest.php` +- `tests/Feature/Accounting/TaxReturnFilingTest.php` +- `tests/Feature/Accounting/TaxReturnPaymentTest.php` +- `tests/Unit/Backup/BackupTableRegistryTest.php` +- `tests/Feature/Backup/CompanyExportEndToEndTest.php` + +## Trace next before changing accounting code + +1. Country selector, wizard step validation, model/API creation and company copying. +2. Every capability's route, action, API/MCP and employee/customer portal checks. +3. All document posters, credits and payment allocation paths; tax-code mutation after posting. +4. Invoice and report PDF templates, foreign-currency conversion and settlement dates. +5. Import/restore validation of country, tax facts and legacy organisation identifiers. +6. Jobs/scheduler and admin overrides that could bypass country capability gates. + +Search terms for repeat audits: `Country::`, `address_country`, `APP_REGION`, +`isCanadian`, `CRA`, `1099`, `GIFI`, `CPP`, `EI`, `QPP`, `CCA`, `GST/HST`, +`America/`, `CAD`, `USD`, `fiscal_year_start_month`. +Search hits are leads, not proof of defects. Preserve legitimate CA/US behaviour. diff --git a/docs/australia/requirements.md b/docs/australia/requirements.md new file mode 100644 index 0000000..94ad50b --- /dev/null +++ b/docs/australia/requirements.md @@ -0,0 +1,72 @@ +# Australian requirements register — initial tranche + +Last checked: 2026-09-11. No requirement below is implemented, independently +reviewed or production-authorised by this milestone. This is not the complete +Australian compliance inventory. Expand it as individual modules are specified. + +## Status and evidence rules + +Track research and delivery separately. Research states: verified-source, +engineering-decision, needs-verification. Delivery states: planned, implemented, +tested, reviewed, released. Digital-service authorisation is an additional field, +not implied by “tested”. Each promoted requirement must record source section, +effective dates, expected results, test IDs, reviewer/date and release version. +Never infer statutory commencement from a website's publication or retrieval date. + +Common initial metadata for all rows: owner = project maintainer (reviewer not yet +appointed); delivery = planned; reviewer/date = pending; release = none; +authorisation = not assessed. Effective dates are unresolved unless stated below. + +| ID | Scope / requirement | Research / authority | Acceptance evidence required | +| --- | --- | --- | --- | +| AU-CORE-001 | AU legal jurisdiction distinct from hosting domain and currency | Engineering decision; `Country`, `Company` | Creation, API, restore and CA/US regressions; invalid jurisdiction rejected | +| AU-CORE-002 | AU regions/timezones and user-confirmed locale defaults | Engineering decision; timezone dataset verification pending | Hobart/DST, half-hour zones, all state choices, no inference of tax residency from browser | +| AU-CORE-003 | AU financial-year default; supported alternative periods | Needs verification: ATO accounting periods | July boundary and alternate-period fixtures; explicit historical period policy | +| AU-CORE-004 | ABN checksum validation | Verified-source: [ABR format](https://abr.business.gov.au/Help/AbnFormat), “To verify an ABN” | Official example passes; changed check digit, non-digits and wrong lengths rejected; storage preserves identifier as text | +| AU-CORE-005 | Separate checksum success from ABR identity/GST-registration lookup | Engineering decision; detailed ABR service/date semantics need verification | Offline/unavailable lookup never reports identity or registration as verified | +| AU-CORE-006 | Effective-dated GST/PAYG registrations and applicable identifiers | Needs verification: ATO/ABR/ASIC | Start/cancel/change scenarios, audit trail and historical documents unaffected | +| AU-CORE-007 | Unsupported country-specific features fail closed | Engineering decision; existing `JurisdictionProfile` | UI/action/API/MCP/portal/admin-override denial tests for AU Canadian/US forms | +| AU-GST-001 | Taxable, GST-free, input-taxed and outside-scope treatment | Needs verification: ATO GST classifications | Independent examples and separate BAS treatment, not a shared zero-rate shortcut | +| AU-GST-002 | Tax invoices/adjustment notes and inclusive/exclusive rounding | Needs verification: ATO tax invoices and adjustment notes | Official field/threshold/rounding requirements captured; mixed-line PDF and calculation fixtures | +| AU-GST-003 | Cash/non-cash attribution, partial settlement and credits | Needs verification: ATO GST accounting methods | Same invoices with different settlements produce independently expected period totals | +| AU-GST-004 | Recoverable tax and business-use apportionment | Needs verification: ATO GST credits | Creditable purpose/evidence and non-recoverable portions separately tested | +| AU-BAS-001 | Simpler/full BAS and IAS labels, rounding and scope | Needs verification: ATO BAS/IAS instructions | Every label reconciles to source transactions with expected independently reviewed totals | +| AU-BAS-002 | Separate preparation, lodgement acceptance and payment | Engineering decision; existing local `TaxReturnFiler` | Snapshot, rejection/retry, amendment and payment states cannot imply one another | +| AU-PAYROLL-001 | Australian withholding, declaration and payment classifications | Needs verification: current ATO PAYG schedules | Official dated examples, boundary and special-case fixtures; no Canadian fallback | +| AU-PAYROLL-002 | Employment instruments, leave, payslips and confidentiality | Needs verification: Fair Work and state legislation | Named-award/state coverage and independently reviewed expected results | +| AU-SUPER-001 | Current contribution basis, deadlines and reporting rules | Needs verification: ATO current super/Payday Super rules | Confirm commencement/transitional rules; no hard-coded historical quarterly assumption | +| AU-STP-001 | Current STP schema, corrections, finalisation and YTD migration | Needs verification: service-specific ATO specifications | Schema/test-environment results and reviewer/provider sign-off before live submissions | +| AU-DSP-001 | Access to ATO digital services requires a separate onboarding gate | Verified-source: [ATO getting started](https://softwaredevelopers.ato.gov.au/getting_started), steps 1–5 | Chosen deployment/service model documented, applicable testing/security and production permission evidence | +| AU-ASSET-001 | Australian book/tax depreciation separation | Needs verification: ATO applicable depreciation regimes | Effective-dated rule fixtures, disposal and business-use cases; no Canadian CCA | +| AU-PRIVACY-001 | TFN/privacy and record-class retention requirements | Needs verification: OAIC, ATO, Fair Work | Applicability analysis, access/redaction tests and retention triggers before collection | +| AU-OPS-001 | AU tables, tax snapshots and attachments survive upgrades/restores | Engineering decision | Legacy/new backup round trips, matching balances and identifiers, tested recovery | +| AU-OPS-002 | CA/US/AU changes tested on both supported databases | Engineering decision; upstream CONTRIBUTING | Commit-linked MySQL/SQLite suite results; no ignored baseline failures | + +## Verified-source details + +AU-CORE-004: ABR describes an 11-digit number validated by subtracting one from +the first digit, multiplying by weights `[10,1,3,5,7,9,11,13,15,17,19]`, and +requiring the sum to be divisible by 89. Its example is `51 824 753 556`. +This is an official public example, not a fixture identifying the user's business. +Source retrieved 2026-09-11; page version 9.9.7. Algorithm effective period is not +stated on the page; verify before release. No implementation/test ID yet. + +AU-DSP-001: ATO's getting-started guidance lists registration, specification-based +development/testing, security evidence and production-access steps. Requirements +must be confirmed for each chosen service and self-hosted/hosted/provider model. +Source retrieved 2026-09-11; page last modified 2025-09-09. Do not interpret this +general guidance as approval for this fork or a complete service specification. +No live integration or external registration is being performed. + +## Unresolved source queue + +Verify detailed tax-invoice guidance (previous retrieval returned HTTP 403), +GST/BAS instructions, payroll schedules, current super changes and service +specifications before implementing rules. Add exact sources and sections per +requirement; a link to an authority's homepage is not sufficient evidence. + +Later tranches must cover entity tax returns, trusts/partnerships, ACNC/DGR, +state payroll tax, FBT, contractors/TPAR, workers compensation/long-service leave, +specialist GST/industry taxes, banking/payment formats and eInvoicing. None is +implicitly covered by this initial register. Rule changes require new dated +evidence and tests; do not overwrite old transaction calculation facts.