# Free4AllHub monthly budget workbench

A focused, original, dependency-free MIT-licensed browser tool for a single month
of planned and actual income and expense entries. It calculates totals, net
amounts and variance, exports flat CSV, and saves a versioned JSON you can reopen
and revise. It is not a full spreadsheet, accounting system, bank connection,
financial recommendation or mature upstream application.

## Run the downloadable source

The public `budget-workbench-source.zip` contains the original source below plus
a compact standalone `index.html`. Its simple Hub link differs from the full
navigation on the hosted website. No other Hub assets are relicensed here.

1. Extract the ZIP, retaining all files in the same directory.
2. Serve that directory with any ordinary static web server. If Python is already
   installed, for example: `python3 -m http.server 8000 --bind 127.0.0.1`.
3. Open `http://127.0.0.1:8000/` in a current browser.

The runtime is plain local HTML, CSS and ES modules. It requires no package
installation, backend, external font, icon, runtime dependency or account.
Direct `file://` launch is not promised because browsers restrict ES modules.
The normal website/static server serves these files; the editor makes no app
network requests and has no storage, upload, telemetry or automatic save.
Ordinary links navigate only when you choose them.

Source files:

- `page.html`: the original main-content fragment, wrapped by the hosted build.
- `style.css`: workbench styles scoped under `.budget-workbench`.
- `core.mjs`: strict schema, integer calculations, exports, replacement state.
- `app.mjs`: safe text DOM, file review and editing UI, browser downloads.
- `tests/core.test.mjs`: Node built-in tests, no installed test dependencies.
- `README.md` and `LICENSE.txt`: usage, limits and full MIT notice.

For a different wrapper, include the fragment in a `<main id="main">`, load
`./style.css`, then load `./app.mjs` with `type="module"`. Keep `core.mjs` beside
`app.mjs`. No inline scripts or handlers are needed. A hosting policy can keep
`script-src 'self'`, `style-src 'self'`, and `connect-src 'none'`.

## A budget you can come back to

1. Choose **Try the fictional example** or **Start blank**. The example is
   deliberately incomplete: its extra-work actual is unrecorded.
2. Set the title, month and one supported currency. Add or remove entries.
3. Enter planned amounts and record actual amounts you know. A blank actual is
   **unrecorded**, not zero. Enter `0` for a known zero.
   Use **Next unrecorded actual** to cycle through blank actual fields. This only
   moves focus, never fills an amount. Known zeroes are skipped; invalid nonblank
   amounts still need correction.
4. Check totals. Recorded actuals are partial until every relevant row has an
   actual. Income/expense total variance is withheld when its group is partial;
   net variance is withheld while any actual is missing.
5. Download **editable budget (JSON)**. CSV is an optional values-only export for
   other tools. A requested download does not prove the file was saved.
6. Open a fresh workbench tab, choose your saved JSON, review its summary, then
   explicitly open it. Check the figures and notes.
7. Revise an entry and download another JSON. Reopen that version too. Keep your
   earlier file until the replacement has been checked.

Reopen JSON in this budget workbench. The shared project-bundle tool supports
version 1 monthly-budget JSON through a pinned native preflight and preserves its
exact bytes. Its generic label and neutral extraction filename do not expose the
file’s title or notes. Bundles still contain those original private bytes and
metadata: they are not encrypted, redacted, synced or automatic restoration.
Choose each file manually, extract it after a fresh bundle reopen, then use this
workbench’s incoming review and explicit replacement. CSV cannot be imported here. Changing currency when entries
exist requires a separate warning and choice: it **relabels values without
converting them**. There are no exchange rates.

## Arithmetic and input rules

The supported two-decimal currencies are USD, EUR, GBP, CAD, AUD, NZD, CHF and INR.
This is a finite allowlist, not a claim of support for all currencies. One budget
has one month and one currency. Changing the currency leaves every number intact.

Amounts are decimal **strings**, such as `"1250.50"`, `"0"` or `"-12.5"`, with no
commas, leading/trailing whitespace, symbols, plus signs, exponents or leading
zeroes. At most two decimal places are allowed. Planned amounts are required;
actual amounts may be the empty string. Original valid strings remain unchanged
in JSON. The calculations parse into exact integer minor units, never floating
point decimal sums. Display and CSV normalize numbers to two decimal places.

Signed adjustments are allowed. A negative expense reduces expense totals; a
negative income reduces income totals. Actual minus planned is row variance.
A positive expense variance means more expense than planned; a positive income
variance means more income than planned. Net is income minus expense. Net
variance is actual net minus planned net. None of these amounts is a bank/cash
balance, a verified transaction total, a savings estimate or spending advice.

Bounds:

- 200 entries in total, income and expense combined.
- Each planned/actual amount: −999999999.99 through 999999999.99.
- Title and entry label: 120 UTF-16 code units, nonblank, single line.
- Per-entry notes: 500 UTF-16 code units. Newlines and tabs are allowed.
- Month: `YYYY-MM`, from 0001-01 through 9999-12.
- JSON file: 1 MiB. This exceeds the maximum serialized size of a valid budget
  under the row/text limits, including maximum-width valid Unicode and escapes.

The maximum rows and per-row bound also keep aggregate sums and net variance well
below JavaScript's exact-integer limit. Invalid fields pause totals and exports;
the UI does not silently round, coerce or show an old valid total as current.
Browser/device failures can still occur below the caps.

## Version 1 JSON format

The exact top-level keys are `schema`, `version`, `title`, `month`, `currency`,
`entries`. No extra keys are accepted. Each entry has exactly `type`, `label`,
`planned`, `actual`, `notes`. Type is `income` or `expense`.

```json
{
  "schema": "free4allhub-monthly-budget",
  "version": 1,
  "title": "Fictional small month",
  "month": "2026-11",
  "currency": "USD",
  "entries": [
    {"type":"income","label":"Fictional pay","planned":"100.00","actual":"100.00","notes":"Practice only"},
    {"type":"expense","label":"Fictional supplies","planned":"25.00","actual":"","notes":"Not yet recorded"}
  ]
}
```

Files must be valid UTF-8 JSON. Byte limits and fatal UTF-8 decoding precede schema
validation. Wrong schema, future version, unknown fields, invalid strings or
amounts and oversized files are rejected. Imported titles, labels and notes are
rendered as text, not HTML. The app retains the current budget while reading,
validating and reviewing. Only the explicit Open/Replace action changes it.
Cancel leaves current work, including invalid edits, alone. There is no merge.

## CSV interoperability and formula-like text

UTF-8 CSV uses comma separators, quoted cells, doubled interior quotes and CRLF
record separators. It has a header and one row per entry, no aggregate rows:

`budget_title, month, currency, type, label, planned, actual,
variance_actual_minus_planned, actual_status, notes`

Actual and variance cells are empty for unrecorded actuals. The explicit
`actual_status` column says `unrecorded` or `recorded`. Notes may contain newlines
inside their quoted cell. Currency and month are repeated for each entry.
An empty budget exports only the header.

Text beginning with a potential spreadsheet formula marker (`=`, `+`, `-`, `@`),
including after leading whitespace/control characters, receives an apostrophe
prefix in CSV. Correct CSV quoting alone is not formula-injection protection.
Validated numeric columns stay numeric, including negative amounts. JSON retains
the original text without the apostrophe. Some spreadsheet importers display the
apostrophe literally or infer other types; behavior varies, and this is not a
universal spreadsheet security guarantee. Check imported CSV before using it.

## Privacy, saving and limits

Entries live only in tab memory. No browser storage, cookies, uploads, accounts,
autosave, recovery service, bank APIs or sync are used. Closing, refreshing or
replacing the tab loses edits. The UI warns, and requests a browser leave warning,
but browsers may omit it. Even a JSON download leaves the tab-only warning because
the app cannot verify your filesystem save. Check and reopen important files.

JSON and CSV contain the title, month, currency, all labels, amounts and notes.
They are plain, unencrypted, unredacted files. Download names use only the month
and currency, not the budget title. Keep the files private when appropriate. Do
not enter account numbers, credentials or unnecessary sensitive information.

This tool does not provide bank reconciliation, multi-month reporting, recurring
entries, charts, formulas, spreadsheet grid editing, XLSX, CSV import, multi-user
collaboration, tax advice, recommendations, automatic backup or financial
correctness of the numbers you entered. It does not claim to replace Excel,
Google Sheets, Grist, Baserow, CryptPad or a full accounting application.

## Source, license and architecture decision

Original code, fictional example, tests, documentation and compact download
wrapper are MIT licensed, copyright 2026 Free4AllHub contributors. Retain the full
notice in `LICENSE.txt`. Your budget content and unrelated Hub material retain
their own rights. No code or assets from an upstream spreadsheet are bundled.

Grist OSS, Baserow and CryptPad were considered as mature upstream alternatives;
their service/backend and persistent-data/operator requirements would exceed
this expressly browser-local, no-account, no-storage budget scope. The small
original core was selected for that boundary, not as a claim of equal features,
quality or maturity. Those applications were not installed or tested as part of
this implementation. No upstream license is borrowed to imply provenance.

## Verification

Run from the extracted source directory:

```sh
node --check core.mjs
node --check app.mjs
node --test tests/*.test.mjs
```

The built-in Node tests cover decimal cents, signed zero and adjustments, blank
actual versus zero, exact totals, partial variance, safe maximum totals, strict
schema/version/currency/month, row/text/byte caps, invalid UTF-8 and Unicode,
worst-case valid Unicode roundtrip size, malicious text, CSV escaping/formula
protection, save/fresh parse/revise/save, and two-step replacement/cancellation.
A UI source check covers safe text rendering, no network/storage calls, leave
warning, and local module structure. These checks are not browser interaction
or accessibility tests.

The parent Hub release workflow separately checks the served route, mobile
layout, actual downloads, fresh-tab reopening, invalid-file preservation, cancel
and currency relabel flows before publication. Consult that release's evidence
for what was actually run. This source does not claim real-beginner completion,
physical-phone, screen-reader, financial, professional security or every-browser
certification. No test can verify the accuracy of figures a visitor supplies.

## Manual Learn → budget continuity

Learn’s existing “A useful checklist” route can hold a supplied planning brief;
it is not a dedicated budgeting lesson or calculator. Export its editable progress
JSON before closing a session-only tab. Keep it with a separately created budget
JSON through Keep & reopen. Each original tool owns native review/restoration.
After extracting a budget, review and reopen it here, revise, save a new JSON and
verify another fresh reopen. Compose a new bundle yourself to include the revision.
No old bundle or Learn record is updated automatically, and this transport is not
a learning assessment. The hosted guide includes explicitly fictional figures.


## Contribute one small improvement

The integrated **Next unrecorded actual** navigation aid is an AI-assisted worked
example. It leaves exact arithmetic, JSON v1, CSV and the pinned project-bundle
parser unchanged. See `CONTRIBUTING.md` and `CREDITS.md`, or the hosted guide at
https://free4allhub.com/contribute/budget/. The guide provides the unchanged
historical candidate, baseline, patch and reproducible kit separately from this
current source download. It does not claim an outside contribution or accepted PR.

No verified public budget submission endpoint, repository or maintainer email
is available. Prepare a local package and ask the project owner through a channel
you already trust to confirm where it should go. No upload or automated publishing
is implemented.
