Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
a543416
spec(027): add localization support spec, plan, and tasks
SteveTeece Aug 27, 2026
9b66bb1
feat(027): localization Setup + Foundational infrastructure (T001-T014)
SteveTeece Aug 27, 2026
7bbb61b
chore(027): record after_implement companion hook state (14/64 tasks)
SteveTeece Aug 27, 2026
2b0e180
feat(027): localize navigation shell + Members module (US1, T015-T028)
SteveTeece Aug 28, 2026
bfa98d3
feat(027): localize Rehearsals module (US2, T032)
SteveTeece Aug 28, 2026
d2b52d5
chore(027): record after_implement companion hook state (29/64 tasks)
SteveTeece Aug 28, 2026
f2b3ed7
feat(027): localize Dashboard page + all dashboard tiles (US2, T031)
SteveTeece Aug 28, 2026
36e4626
feat(027): localize remaining menu providers + author enum resource k…
SteveTeece Aug 28, 2026
4769073
feat(027): localize shared components (US2, T037)
SteveTeece Aug 28, 2026
15c8af0
feat(027): localize Events / AGM module (US2, T033)
SteveTeece Aug 28, 2026
b406f6f
feat(027): localize Settings page + tabs (US2, T035)
SteveTeece Aug 28, 2026
b0c333f
feat(027): localize Setup Wizard (US2, T036)
SteveTeece Aug 28, 2026
8aa9dd9
feat(027): localize StartupError page + Reports page shell (US2, T043)
SteveTeece Aug 28, 2026
6abdabd
feat(027): localize Finance module (US2, T034)
SteveTeece Aug 28, 2026
e776237
feat(027): localize AgeCalculationService DOB/age messages (US2, T041…
SteveTeece Aug 28, 2026
6d68cee
chore(027): record companion context after T034 + T041 groundwork
SteveTeece Aug 28, 2026
a8ac20d
feat(027): localize the 11 report providers (US2, T039 + T030)
SteveTeece Aug 28, 2026
f860e34
chore(027): record after_implement companion context (39/64 tasks)
SteveTeece Aug 28, 2026
c3529e1
feat(027): localize report PDF renderer chrome (US2, T040) + enum/cur…
SteveTeece Aug 28, 2026
0230082
feat(027): localize non-Finance service exception messages (US2, T041…
SteveTeece Aug 28, 2026
fee784b
feat(027): finish US2 — localize Finance exception messages + repo-wi…
SteveTeece Aug 28, 2026
73e37f0
feat(027): US3 — persisted, OS-aware display language + pickers (T046…
SteveTeece Aug 28, 2026
3944380
feat(027): Polish — repo-wide literal guard + localize App.razor + do…
SteveTeece Aug 28, 2026
1912854
feat(027): add American English (en-US) resource set
SteveTeece Aug 28, 2026
afeefd1
feat(027): add French (fr-FR) resource set
SteveTeece Aug 28, 2026
88fb606
spec(028): add international accounting-practice readiness spec, plan…
SteveTeece Aug 29, 2026
f75ed7e
feat(028): foundational currency primitives + Settings schema (T001-T…
SteveTeece Aug 29, 2026
19ab79f
feat(028): US1 configurable currency — MoneyFormatter drives all mone…
SteveTeece Aug 29, 2026
1dd0917
feat(028): US2 locale-safe money entry — MoneyInput.Parse for numeric…
SteveTeece Aug 29, 2026
6a24d5f
chore(028): sync companion after_implement context (Phase 4 / US2)
SteveTeece Aug 29, 2026
f4b84b2
chore(028): record plug-display concern for Polish T091a
SteveTeece Aug 29, 2026
964b024
feat(028): US3 statement integrity — Balance Sheet / Trial Balance gu…
SteveTeece Aug 29, 2026
1be7ea9
chore(028): sync companion after_implement context (Phase 5 / US3)
SteveTeece Aug 29, 2026
cc13d63
feat(028): US4 basis-of-accounting disclosure on financial statements…
SteveTeece Aug 29, 2026
f43f457
feat(028): US5 conventional bank reconciliation (T048-T051)
SteveTeece Aug 29, 2026
2ee9c7f
chore(028): sync companion after_implement context (Phase 7 / US5)
SteveTeece Aug 29, 2026
ef37509
feat(028): US6 closed-period lock (T052-T064)
SteveTeece Aug 29, 2026
01c8361
chore(028): sync companion after_implement context (Phase 8 / US6)
SteveTeece Aug 29, 2026
2fccd72
feat(028): US7 financial-year start as a setup decision (T065-T075)
SteveTeece Aug 29, 2026
32fe41d
chore(028): sync companion after_implement context (Phase 9 / US7)
SteveTeece Aug 29, 2026
895dcf5
chore(028): companion after_implement task-sync (75/94)
SteveTeece Aug 29, 2026
d950e83
feat(028): US8 audit retention, coverage & purge-failure surfacing (T…
SteveTeece Aug 29, 2026
3b802cc
docs(028): US9 accounting policies + living-spec currency (T084-T086a)
SteveTeece Aug 29, 2026
620ce00
chore(028): companion after_implement task-sync (85/94)
SteveTeece Aug 29, 2026
1c7643d
docs(028): US10 sales-tax internationalisation assessment spike (T087…
SteveTeece Aug 29, 2026
91cf0a3
test(028): Phase 13 polish — currency-symbol guard + SC evidence (T09…
SteveTeece Aug 29, 2026
c220045
chore(028): companion after_implement task-sync (92/94)
SteveTeece Aug 29, 2026
92cfeec
chore(028): file follow-on issues #353-#356, close #341 + sub-issues;…
SteveTeece Aug 29, 2026
0ea3ebc
feat(028): sub-twelve-month first financial year, labelled a part-yea…
SteveTeece Aug 30, 2026
58fa1f3
feat(028): tax-exclusive amount entry (net + tax), alongside tax-incl…
SteveTeece Aug 30, 2026
596929b
feat(028): classify recoverable input tax (2320) as a Balance Sheet a…
SteveTeece Aug 30, 2026
f98e046
docs(028): retire ABN/GST wording from settings living spec (#356)
SteveTeece Aug 30, 2026
00284b6
docs(028): retire ABN/GST wording across the other living specs (#356)
SteveTeece Aug 30, 2026
f4f7a0b
chore(028): seed a complete 2026 — rehearsals to year-end, 65% attend…
SteveTeece Aug 30, 2026
fe2b642
chore(028): anchor seed data to the real run date so future dates sta…
SteveTeece Aug 30, 2026
af61b68
docs: add Claude Code to the README tools-used list
SteveTeece Aug 30, 2026
e2b872c
Merge branch '028-international-accounting-standards' into dev
SteveTeece Aug 30, 2026
13b2bf8
Add script to remove sample data
SteveTeece Aug 30, 2026
b31673a
chore(seed): generate organisation name and fee settings in the debug…
SteveTeece Aug 30, 2026
808d334
fix: point delete-database.cmd at the real MAUI app-data path
SteveTeece Aug 30, 2026
f0d6049
fix: language selector only offered Australian English (#360)
SteveTeece Aug 30, 2026
ffe134a
docs(029): spec — first-run language selection & optional sample-data…
SteveTeece Aug 30, 2026
35d80ba
docs(029): apply language changes live in-session, drop all restart p…
SteveTeece Aug 30, 2026
72a3b75
docs(029): plan — first-run language selection & sample-data seeding
SteveTeece Aug 30, 2026
aa5b3aa
chore(029): record plan-step completion in companion state
SteveTeece Aug 30, 2026
7743983
docs(029): tasks — first-run language selection & sample-data seeding
SteveTeece Aug 30, 2026
7d61bc6
feat(029): foundational language-preference store + first-run screen …
SteveTeece Aug 30, 2026
b642524
feat(029): complete US1 — retire wizard language step & sample-data o…
SteveTeece Aug 30, 2026
b407bed
chore(029): fix companion step-summary misfile (specify -> implement)
SteveTeece Aug 30, 2026
ecabcf4
feat(029): US2 — Settings language change applies live, restart notic…
SteveTeece Aug 30, 2026
6416ba0
chore(029): record US2 verification in companion state
SteveTeece Aug 30, 2026
5b0a885
feat(029): US3 — Debug-only sample-data loading from first-run screen
SteveTeece Aug 30, 2026
bde8bc2
chore(029): phase 6 polish — docs refreshed, full suite green; live v…
SteveTeece Aug 30, 2026
82074ce
chore(029): close T037 — Settings language change manually verified live
SteveTeece Sep 2, 2026
e945af0
fix(029): in-session language switch dead in real MAUI host — set cul…
SteveTeece Sep 2, 2026
e77c889
fix: address PR #363 code review — simplicity & correctness cleanups
SteveTeece Sep 2, 2026
249f3ad
Merge pull request #363 from SteveTeece:029-first-run-language-seed
SteveTeece Sep 2, 2026
1340757
Merge pull request #364 from SteveTeece/master
SteveTeece Sep 2, 2026
5bd56d6
fix(ci): escape RID separator in macOS debug pre-release publish (#366)
SteveTeece Sep 2, 2026
eacbb0a
Merge pull request #371 from SteveTeece:fix/366-mac-build-rid-escape
SteveTeece Sep 2, 2026
0e2ac01
ci: use plural RuntimeIdentifiers for the Mac universal debug build
SteveTeece Sep 2, 2026
17a2554
Merge pull request #372 from SteveTeece:fix/mac-prerelease-runtimeide…
SteveTeece Sep 2, 2026
4db629a
ci: set Mac universal RIDs in the csproj, not on the publish CLI
SteveTeece Sep 2, 2026
42c1ece
fix(finance): pin currency negative pattern so AUD negatives never drift
SteveTeece Sep 2, 2026
b3baf86
Merge pull request #374 from SteveTeece:fix/mac-prerelease-universal-…
SteveTeece Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
20 changes: 15 additions & 5 deletions .github/workflows/debug-pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,27 @@ jobs:
# No CodesignKey/EnableCodeSigning -> the build applies only an ad-hoc signature
# (all an internal test build needs; testers still have to clear the Gatekeeper
# quarantine flag — see the release notes text in publish-release).
# Passing BOTH RIDs in a single RuntimeIdentifier value is how the .NET MAUI Mac
# Catalyst targets emit a universal (lipo'd x64 + arm64) binary. Release builds do
# this by default; a Debug build has to state it explicitly. See
# https://learn.microsoft.com/dotnet/maui/mac-catalyst/deployment/publish-unsigned
# PublishMacUniversal=true flips a conditional PropertyGroup in StageFright.App.csproj
# that sets the *plural* <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</...>,
# which is what makes MAUI's Mac Catalyst targets emit a universal (lipo'd x64 + arm64)
# .app. It has to be set inside the .csproj, not passed here as -p:RuntimeIdentifier(s):
# * the singular RuntimeIdentifier is validated by the .NET SDK as ONE RID and rejects
# a `;`-list with "NETSDK1083: ... 'maccatalyst-x64;maccatalyst-arm64' is not
# recognized";
# * passing -p:RuntimeIdentifiers on the CLI makes it a global property that leaks the
# `;`-list verbatim into every ProjectReference (the plain non-maccatalyst class
# libraries), which then fail the same NETSDK1083.
# As a project property it is evaluated locally and MAUI fans out per-RID inner builds
# that hand a single concrete RID to the referenced libraries. Release builds get this
# universal RID set by MAUI automatically; a Debug build has to opt in. See the
# dotnet/macios .NET 8 release notes and dotnet/maui's Controls.TestCases.HostApp.csproj.
- name: Publish unsigned universal .app
run: >
dotnet publish ${{ env.APP_PROJECT }}
-f ${{ env.TFM }}
-c Debug
-p:CreatePackage=false
-p:RuntimeIdentifier="maccatalyst-x64;maccatalyst-arm64"
-p:PublishMacUniversal=true

# `ditto` is Apple's supported way to archive an .app bundle for transport — it
# preserves the symlinks, permissions, and resource forks that a plain `zip`
Expand Down
4 changes: 1 addition & 3 deletions .specify/feature.json
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
{
"feature_directory": "specs/026-past-agm-committee-report"
}
{"feature_directory":"specs\\029-first-run-language-seed"}
26 changes: 20 additions & 6 deletions CLAUDE.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="10.0.10" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="10.0.90" />
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The master branch will always contain the code for the most recent release. The
Make a fork of this repo and use that as your private scratch pad. When you are ready for a review and merge, create a pull request to dev.

## Tools used
* Claude Code -Sonnet 5 model (https://www.anthropic.com/claudecode)
* Github Spec Kit (https://github.com/github/spec-kit)
* SpecKit Companion (https://github.com/alfredoperez/speckit-companion)

Expand Down
1 change: 1 addition & 0 deletions StageFrightCommunity.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<Project Path="tests/StageFright.Core.Tests/StageFright.Core.Tests.csproj" />
<Project Path="tests/StageFright.Data.Tests/StageFright.Data.Tests.csproj" />
<Project Path="tests/StageFright.Integration.Tests/StageFright.Integration.Tests.csproj" />
<Project Path="tests/StageFright.Localization.Tests/StageFright.Localization.Tests.csproj" />
<Project Path="tests/StageFright.Reports.Tests/StageFright.Reports.Tests.csproj" />
<Project Path="tests/StageFright.TestPlugin/StageFright.TestPlugin.csproj" />
<Project Path="tests/StageFright.UI.Tests/StageFright.UI.Tests.csproj" />
Expand Down
9 changes: 7 additions & 2 deletions capabilities/app-host/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ The app shell MUST ask a setup-completion service whether initial configuration

### The setup wizard captures required configuration through validated steps before anything else can run

The wizard MUST require organisation identity and tax details, fee/renewal configuration, and GST treatment before allowing submission, gating advancement on a per-step validation pass rather than only validating at final submit. Completion MUST persist configuration through one setup service call and then route straight into the app.
The wizard MUST require organisation identity, fee/renewal configuration, and sales-tax treatment (applicability, rate, and per-fee tax codes) before allowing submission, gating advancement on a per-step validation pass rather than only validating at final submit. Completion MUST persist configuration through one setup service call and then route straight into the app.

#### Scenario: user attempts to advance past an incomplete step
- **WHEN** required fields for the current step fail validation
Expand All @@ -73,7 +73,7 @@ The wizard MUST require organisation identity and tax details, fee/renewal confi

### Optional sample-data seeding is a debug-only, opt-in, non-blocking capability

Sample-data seeding MUST NOT be offered or reachable in release builds, MUST require explicit user opt-in even when available, and MUST run without freezing the setup UI, reporting incremental progress back to it. It MUST also be safe to invoke against a database that already has data. The opt-in control lives on the Organisation Settings tab (the wizard's first tab), and selecting it disables the Chart of Accounts, Opening Balances, and Committee tabs — sample data supplies that information itself, so manual entry on those tabs is bypassed rather than merely optional.
Sample-data seeding MUST NOT be offered or reachable in release builds, MUST require explicit user opt-in even when available, and MUST run without freezing the setup UI, reporting incremental progress back to it. It MUST also be safe to invoke against a database that already has data. The opt-in control lives on the Organisation Settings tab (the wizard's first tab), and selecting it disables the Chart of Accounts, Opening Balances, and Committee tabs — sample data supplies that information itself, so manual entry on those tabs is bypassed rather than merely optional. The seeder likewise stamps its own generated organisation name and fee schedule over the Organisation Settings inputs, so the sample dataset is internally consistent regardless of the placeholder values entered to satisfy the wizard's own validation; currency, language and sales-tax treatment are the exception and follow what the coordinator configured.

#### Scenario: release build reaches the setup wizard
- **WHEN** no debug seeder is registered in the container
Expand All @@ -95,6 +95,11 @@ Sample-data seeding MUST NOT be offered or reachable in release builds, MUST req
- **WHEN** the checkbox is checked after an account, opening balance, or committee title was already queued
- **THEN** every queued entry is discarded so it is never submitted alongside the seeded sample data

#### Scenario: sample data overrides the organisation identity and fee inputs
- **WHEN** the seeder runs after setup was submitted with a placeholder organisation name and fee figures
- **THEN** the persisted settings carry the seeder's generated organisation name, annual fee, attendance fee and renewal configuration instead
- **AND** the currency, language and sales-tax treatment chosen during setup are left unchanged

### Plugin assemblies are discovered and loaded in isolation from each other and from the host

The host MUST scan a known plugins directory for assemblies at startup, load each in its own isolated load context, and contain any single assembly's load failure so it neither aborts discovery of the remaining assemblies nor crashes startup. A missing plugins directory MUST NOT be treated as an error.
Expand Down
4 changes: 2 additions & 2 deletions capabilities/audit-trail/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ In the MVP, every audit entry SHALL attribute the action to a fixed "system" ide

### Audit history ages out on a rolling retention window instead of soft-delete

Unlike other entities, audit entries carry no soft-delete fields — they SHALL instead be hard-deleted once older than a fixed retention period (12 months), evaluated at application startup. This keeps the audit log bounded over time without ever allowing an individual entry to be edited or archived.
Unlike other entities, audit entries carry no soft-delete fields — they SHALL instead be hard-deleted once older than the organisation's configured retention period, evaluated at application startup. The retention period is user-configurable from 1 to 7 years (`Settings.AuditRetentionYears`) and defaults to **5 years** on a new dataset; an existing dataset keeps whatever value it was already configured with. This keeps the audit log bounded over time without ever allowing an individual entry to be edited or archived.

#### Scenario: startup retention purge runs

- **WHEN** the application starts
- **THEN** all audit entries older than 12 months are permanently removed from the store
- **THEN** all audit entries older than the configured retention period (default 5 years) are permanently removed from the store

### Retention purge failures never block application startup

Expand Down
2 changes: 1 addition & 1 deletion capabilities/data-access/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Member and account balance queries (`GetMemberBalanceAsync`, `GetAccountBalanceA
- **THEN** a `ValidationException` naming the reason is thrown before any database write is attempted

#### Scenario: archiving a system account
- **WHEN** any of the seeded system accounts (Cash, Member Receivable, Bad Debt Expense, GST Collected/Paid, Opening Balance Equity, Accumulated Surplus) is archived
- **WHEN** any of the seeded system accounts (Cash, Member Receivable, Bad Debt Expense, Tax Collected, Tax Receivable, Opening Balance Equity, Accumulated Surplus) is archived
- **THEN** the operation is rejected regardless of whether it is referenced by transactions

### Account numbers are allocated deterministically within a fixed range per account type
Expand Down
8 changes: 4 additions & 4 deletions capabilities/domain-model/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ Every type in `StageFright.Core/Exceptions/` SHALL be a `sealed class` deriving

### Fields that snapshot state at posting/accrual time are immutable and never retroactively rewritten

Several entities stamp a value at the moment of creation that reflects "the rule in force then," and that value SHALL NOT be updated even if the organization-wide rule later changes: `Transaction.GstCode`, `Transaction.GLAccount`, and `Fee.GstCode` are all fixed at posting/accrual time; `Account.AccountNumber` is fixed at account creation. Historical rows are read literally, never recalculated against current settings.
Several entities stamp a value at the moment of creation that reflects "the rule in force then," and that value SHALL NOT be updated even if the organization-wide rule later changes: `Transaction.TaxCode`, `Transaction.GLAccount`, and `Fee.TaxCode` are all fixed at posting/accrual time; `Account.AccountNumber` is fixed at account creation. Historical rows are read literally, never recalculated against current settings.

#### Scenario: GST registration status changes
#### Scenario: sales-tax applicability changes

- **WHEN** an organisation's `Settings.IsGstRegistered` flag changes after some fees/transactions were already posted
- **THEN** existing `Fee.GstCode` and `Transaction.GstCode` values on prior rows are left untouched; only newly created rows use the new setting
- **WHEN** an organisation's `Settings.IsTaxApplicable` flag changes after some fees/transactions were already posted
- **THEN** existing `Fee.TaxCode` and `Transaction.TaxCode` values on prior rows are left untouched; only newly created rows use the new setting

#### Scenario: an account's legacy number scheme is queried

Expand Down
Loading
Loading