# Project pack: Wallos @ becd8a3

Facts about **Wallos** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v1.md). This pack is pinned to one version and never changes after publication.

> Wallos is a personal subscription tracker. Add Netflix, gym, insurance or any recurring bill, and it shows what you spend each month, what renews next, and sends reminders before you're charged. It runs on your own computer or server, so your spending data stays private.

## Version and source
- Repository: https://github.com/ellite/Wallos
- Pinned commit: `becd8a3c714f40ed7f5a53bec0118963e88368cf`. Use exactly this version.
- Get it: `git clone https://github.com/ellite/Wallos wallos && cd wallos && git checkout becd8a3c714f40ed7f5a53bec0118963e88368cf`
- Or download a zip: https://github.com/ellite/Wallos/archive/becd8a3c714f40ed7f5a53bec0118963e88368cf.zip
- Live demo: https://demo.wallosapp.com (username: demo / password: demo). Shared demo; the database resets every 2 hours. Don't enter real data.
- Licence: **GPL-3.0-only**. Free to use and change. If you share your changed version with other people (give them the code or app), you must share your source code under the same licence. Using it privately for yourself or your household has no extra obligations.

## Running it
- Easiest: docker run -d --name wallos -p 8282:80 -e TZ=Europe/London -v wallos-db:/var/www/html/db -v wallos-logos:/var/www/html/images/uploads/logos bellamy/wallos:latest # then open http://localhost:8282
- Needs: Docker (recommended) or PHP 8.3 with nginx/apache
- Develop: `docker build -t wallos-dev . && docker run --rm -p 8282:80 -v wallos-db:/var/www/html/db wallos-dev`
- Test: `dev/test.sh`
- Stack: php, javascript, css (vanilla PHP 8.3, vanilla JS). Difficulty for a non-developer with an AI: **easy**. Plain PHP pages and endpoints with no build step, and a single SQLite file. Most changes are a page, an endpoint, a CSS file or a translation file.

## Customisation points (settings → extend → code)
- **currency-and-language** [settings]: Main currency, extra currencies and the interface language (30+ languages). → `Settings → Currencies / Language (translations in includes/i18n/*.php)`
- **categories-and-payers** [settings]: Group subscriptions your way and record who pays for each one. → `Settings → Categories, Household members, Payment methods`
- **notifications** [settings]: How many days before a renewal to remind you, and which channel to use. → `Settings → Notifications (code in endpoints/notifications/ and endpoints/cronjobs/sendnotifications.php)`
- **theme** [extend]: Colours, dark mode and custom CSS without touching PHP. → `Settings → Theme / Custom colours; styles/theme.css, styles/dark-theme.css, styles/themes/`
- **webhooks-and-api** [extend]: Send reminders anywhere (e.g. WhatsApp through a webhook bridge) or read your subscriptions from scripts. → `Settings → Notifications → Webhook; api/ folder (see API documentation in README)`
- **pages-and-stats** [code]: New screens, new statistics and new fields. → `Top-level *.php pages (index.php, stats.php, calendar.php), includes/stats_calculations.php`
- **database-schema** [code]: New fields, such as "cancel by" date or "shared with". → `migrations/*.php (append a new numbered migration; never edit old ones)`

## Must keep working
- Existing data must survive. Add new migrations; never edit or delete old ones.
- Login, registration and password reset flows.
- The cron jobs listed in the README (next payment, exchange rates, notifications).
- Input validation and SSRF protections in includes/inputvalidation.php and includes/ssrf_helper.php.

## Staying updatable
Prefer settings, themes and webhooks first. Keep code changes in new files where possible (e.g. a new page plus one menu link) so that pulling future Wallos updates stays easy.

## Data, costs and safety
- Personal data: **yes**. Stored in: SQLite file in /var/www/html/db (a Docker volume when using Docker). Back up the db folder and the logos folder. Payment amounts and service names are personal financial data.
- Service: Fixer API (exchange rates) (optional, free tier): Converts subscriptions in other currencies into your main currency.
- Service: Notification channels (email, Discord, Telegram, Pushover, Gotify, ntfy, webhooks) (optional, free): Payment reminders.
- Service: AI recommendations (OpenAI, Gemini or local Ollama) (optional, pay-per-use for cloud providers): Optional suggestions to save money.
- Setting `TZ`: Your time zone, so reminders are sent at the right time (e.g. Europe/London).
- Setting `OIDC_CLIENT_SECRET` (**secret**: the person enters it themselves, never in chat): Only if you connect a single sign-on provider. Never paste the value into an AI chat.
- Self-hosted with its own login. Use a strong password, and put it behind HTTPS before exposing it to the internet.
- AI recommendations send subscription names and prices to the chosen AI provider. Use Ollama to keep them local.

## Coding conventions (BespokeAI notes; the project has no AGENTS.md)
#### Snapshot
- PHP 8.3 server-rendered app, vanilla JavaScript, SQLite. No framework, no build step, no Composer for the app itself.
- Served by nginx and PHP-FPM inside the `bellamy/wallos` Docker image. Cron jobs run inside the container.

#### Commands
```bash
docker build -t wallos-dev .                                   # build the image from your working copy
docker run --rm -p 8282:80 -v wallos-db:/var/www/html/db wallos-dev   # run it at http://localhost:8282
dev/test.sh                                                    # test suite in a throwaway container (Podman by default)
CONTAINER_ENGINE=docker dev/test.sh                            # same, using Docker
php -l <file.php>                                              # syntax-check a PHP file (inside the container if PHP isn't installed)
```

#### Rules
- Schema changes: add `migrations/<next number>.php`. Never edit or reorder existing migrations.
- Text: use translation keys and add them to `includes/i18n/en.php`.
- Validate all input with the helpers in `includes/inputvalidation.php`. Anything that fetches a URL must go through `includes/ssrf_helper.php`.
- Endpoints check the session (`includes/connect_endpoint.php` / `validate_endpoint.php`). Keep these checks in new endpoints.
- Keep diffs small. Prefer new files plus a link over rewriting existing pages.
- Never commit `db/*.db` or uploaded logos.

---

# Customising Wallos

Wallos is the easiest project in the catalogue to adapt. It's plain PHP with no build step: change a file, refresh the browser.

## How the code is laid out

| You want to change… | Look in |
|---|---|
| A page (dashboard, stats, calendar, settings) | Top-level `index.php`, `stats.php`, `calendar.php`, `settings.php`, `profile.php` |
| What happens when you click Save/Delete | `endpoints/<area>/*.php` (subscriptions, categories, notifications, household…) |
| Shared helpers (currency formatting, stats, upcoming payments) | `includes/*.php` |
| Database tables/columns | `migrations/0000NN.php`. Add the **next number**; never edit old ones |
| Text and translations | `includes/i18n/en.php` (+ other languages; keys must exist in `en.php`) |
| Colours, fonts, dark mode | `styles/theme.css`, `styles/dark-theme.css`, `styles/themes/`, `styles/styles.css` |
| Scheduled jobs (reminders, exchange rates) | `endpoints/cronjobs/*.php`, schedule in `cronjobs` |
| Notification channels | `endpoints/notifications/save*.php` + `endpoints/cronjobs/sendnotifications.php` |
| Public API | `api/` (documented in the README's API section) |

## Use the gentlest change first

1. **Settings (no code):** currencies, language, categories, household members, payment methods, reminder timing, theme colours.
2. **Extend:** custom colours/CSS, webhooks for notifications (e.g. a Telegram bot or a WhatsApp bridge), the API for scripts.
3. **Code:** new pages, new fields, new statistics. Prefer **new files** plus a small link from an existing page.

## Recipes

- **New field on a subscription** (e.g. `shared_with`):
  1. Add a migration.
  2. Add the input to the add/edit form in `index.php` / `includes/subscription_details_popup.php`.
  3. Save it in `endpoints/subscription/`.
  4. Show it in `includes/list_subscriptions.php`.
  5. Add translation keys to `en.php`.
- **New report page:** copy the structure of `stats.php`, put calculations in a new `includes/*_calculations.php`, and link it from the header (`includes/header.php`).
- **New reminder rule:** extend `endpoints/cronjobs/sendnotifications.php`. Test it by running the cron script by hand inside the container: `docker exec wallos php /var/www/html/endpoints/cronjobs/sendnotifications.php`.

## Running and checking your changes

- Quickest: run the Docker image and mount your copy of the code. Alternatively, build it with `docker build -t wallos-dev .`
- Tests: `dev/test.sh` (needs Docker or Podman; runs in a throwaway container).
- Always check the add, edit and delete flows for a subscription, the dashboard totals, and dark mode after changing things.

## Pitfalls

- Every database change must be a **new** migration, or existing users lose data.
- Keep input validation (`includes/inputvalidation.php`) and SSRF protection (`includes/ssrf_helper.php`) in place for anything that fetches URLs.
- Translations: add new keys to `en.php`. Missing keys in other languages fall back to English.
- Don't commit the `db/wallos.db` file. It contains personal data.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/wallos/becd8a3/bespoke.yaml) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/wallos/becd8a3/SKILL.md)
