# StarPost Backend

Documentation formatting follows [the shared Markdown display contract](../MARKDOWN-DISPLAY-STYLE.md).

Production API and background-processing service for StarPost orders, payments,
postcard delivery, email, QR artifacts, tax evidence, and blockchain sealing.

## Operator commands

Run these commands from `/home/ubuntu/starpost-backend/scripts`.

```text
┌──────────┬─────────────────────────────────────────────┬────────────┐
│ Action   │ Command                                     │ Restart    │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ Full     │ ../tools/verify-server.sh                   │ No         │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ Verify   │ ./deploy-backend-hotfix.sh --verify         │ No         │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ Deploy   │ ./deploy-backend-hotfix.sh                  │ On change  │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ URL bump │ ./deploy-backend-hotfix.sh --url-version    │ On change  │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ Sync OP2 │ ./deploy-backend-hotfix.sh --sync-op2       │ OP2 change │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ DB check │ ./deploy-backend-db-migrations.sh           │ No         │
├──────────┼─────────────────────────────────────────────┼────────────┤
│ DB apply │ ./deploy-backend-db-migrations.sh --apply   │ No         │
└──────────┴─────────────────────────────────────────────┴────────────┘
```

The final command modifies the production database and requires typing
`MIGRATE`. See [scripts/README.md](scripts/README.md) for the complete operator
guide and file reference.

`releases/current-release.json` is the compatibility source of truth. It keeps
one release ID with the active OP2 bundle version and template-image URL version;
the deployment orchestrator validates both components together.

## Project structure

    src/                    API, jobs, services, pages and configuration
    data/                   Persistent runtime health state
    migrations/             Versioned PostgreSQL schema migrations
    design/postcard/         Versioned shared OP2 postcard bundles
    contracts/               Backend integration contracts
    scripts/                 Operator entry points and internal helpers
    tools/                   Full verification and documentation checks
    releases/                Deployment audit and current-release records
    hotfix-backups/           Automatic source rollback snapshots
    ecosystem.config.cjs     PM2 process definition
    rds-ca-bundle.pem        RDS certificate authority bundle

`data/cron-health-state.json` preserves the last 50 runs for every backend
cronjob across PM2 restarts. The service migrates the former project-root file
automatically on first start.

Historical `.env` copies, loose patch files, dated source copies, old script
trees, and the former `production/frontend/` mirror do not belong in the active
project tree. `design/`, `releases/`, and `hotfix-backups/` are runtime or audit
data and must not be treated as general clutter.

## Local development

Install dependencies:

    npm ci

Start with file watching:

    npm run dev

Start without file watching:

    npm start

Node.js 20 or newer is required.

## Configuration

Production secrets are loaded server-side from AWS Secrets Manager. Browser
code uses same-origin `/api/...` requests; frontend URL configuration does not
belong in this backend README.

Do not commit credentials, private keys, database passwords, or production
secret values. The RDS CA bundle is used to verify encrypted database
connections in production.

## Health checks

Full read-only backend verification:

    ./tools/verify-server.sh

This checks syntax, documentation, layout, permissions, dependencies, the RDS
CA, disk space, release records, persistent and live cron health, PM2/systemd,
database reads, AWS configuration, generated filesystem clutter, and every
local/public image and OP2 asset. Before the final result, it prints a bounded
tree with data, release, design, and rollback summaries. It does not restart
PM2, run jobs, apply migrations, or modify production data.

Local API health:

    curl -fsS http://127.0.0.1:3000/health

Public configuration contract through the local API:

    curl -fsS http://127.0.0.1:3000/api/config

Full asset and OP2 smoke tests run automatically through the backend deployment
orchestrator.

## Deployment rules

- Stage backend JavaScript under `/home/ubuntu/starpost-backend-hotfix/src/`.
- For an emergency single-file edit, use `--stage-edit src/routes/config.js`;
  it edits `/home/ubuntu/starpost-backend-hotfix/src/routes/config.js`.
- Use the normal deployment command for backend changes.
- Use `--sync-op2` when only OP2 needs comparison and synchronization.
- Run database migrations only for an intentional schema change or backfill.
- Do not run files inside `scripts/internal/` directly.
- Do not manually restart PM2 during an orchestrated deployment.

Every deployment attempt is recorded in `releases/deployment-runs.jsonl`.
Only a successful deployment containing real changes updates
`releases/current-release.json`.
# Business analytics and conversion

The backend owns anonymous business attribution. Browser sessions expire after
30 minutes of inactivity and never contain an IP address. Stripe metadata carries
the anonymous session UUID; CRM counts a conversion only after the signed Stripe
webhook stores a paid payment with `webhook_processed = true`.

Apply `migrations/039_business_analytics.sql` through the normal database
migration command before deploying the related backend source. The daily cleanup
aggregates completed days and removes individual events and sessions after 30
days.

## Verification cache

The backend full verifier keeps repeated checks light.

Normal command:

    ./tools/verify-server.sh

Normal runs always check live health, PM2, AWS config, database schema, cronjobs, release records and routing.
When asset versions are unchanged, repeated heavy file requests are skipped.

Detailed cached check lines:

    ✓ Template images unchanged | skipped 8 file requests
    ✓ UI assets unchanged | skipped 20 file requests
    ✓ OP2 fonts unchanged | skipped 36 file requests

Final cached summary:

    Cache: skipped unchanged requests - template img 8 | ui assets 20 | OP2 fonts 36

Force a full public re-fetch only when needed:

    ./tools/verify-server.sh --fresh

Fresh runs show requested file counts:

    ✓ Template images checked | requested 8 file requests
    ✓ UI assets checked | requested 20 file requests
    ✓ OP2 fonts checked | requested 36 file requests

Final fresh summary:

    Fresh requests: template img 8 | ui assets 20 | OP2 fonts 36

Private cache file:

    /home/ubuntu/starpost-backend/data/verify-backend-cache.json

