<!-- Canonical: https://programkit.dev/docs/self-hosting/administration -->
<!-- Markdown: https://programkit.dev/docs/self-hosting/administration.md -->

# Administer a self-hosted installation

Self-hosting transfers control of infrastructure and data to the operator. It also transfers the
responsibility for access review, delivery configuration, updates, backups, monitoring, and
incident response.

## Routine product administration

### Accounts and event access

- Keep organizer signup invite-only unless the installation intentionally serves the public.
- Give every operator an individual account.
- Use viewer access for read-only stakeholders.
- Review membership when a project begins, changes phase, or ends.
- Review account sessions after a lost device or credential concern.

### API keys

- Create one event-scoped key per client.
- Use the narrowest preset or scopes.
- Prefer a finite expiry.
- Save the copy-once secret in the client's secret manager.
- Confirm **Last used** after replacing a key, then revoke the old one.
- Never use an API key to work around missing human authorization.

### Files

R2 stores file bytes while the event workspace stores metadata and lifecycle state. Owners can
delete a version; ProgramKit first commits a durable tombstone and removes it from projections,
then deletes the R2 object and records confirmation. Failed cleanup remains visible and retriable.

This is not a complete retention program. Add malware scanning, orphan discovery, age-based
retention, legal holds, offboarding, and usage alerts before accepting sensitive files at scale.

### Email

Watch the communications delivery history for pending, failed, retrying, and delivered messages.
The application outbox preserves resolved recipients and provider attempts, but the deployment
operator still owns sender reputation, bounce handling, suppression, and provider health.

## Updates

Treat the repository as the application source of truth:

1. read the incoming diff and migration notes;
2. export important events and R2 objects;
3. run `npm run setup` and `npm run verify`;
4. deploy a staging Worker or isolated installation;
5. exercise owner login, event switching, uploads, API, MCP, and public pages;
6. deploy the production installation; and
7. monitor errors and critical journeys.

Do not delete or rewrite Durable Object migration tags during an upgrade. Pin the source revision
used by every deployment so the operator can identify the running version.

## Rollback

A Worker code rollback does not automatically roll back Durable Object state or R2 files. Before a
high-risk release, retain:

- the prior source revision and deploy artifact;
- current logical event exports;
- an R2 object manifest and backup where policy requires it; and
- the current Cloudflare recovery bookmark or deployment metadata.

Roll back code only when it remains compatible with any data migrations already applied. Otherwise
restore forward with a corrective release.

## Backup and recovery boundaries

ProgramKit has four related but separate recovery units:

| Unit                   | Contains                                                 |
| ---------------------- | -------------------------------------------------------- |
| Event workspace object | Program, revisions, operations, and audit state          |
| Account objects        | Identities, password state, sessions, event list         |
| Event access objects   | Membership, invitations, participant directory, API keys |
| R2 bucket              | Uploaded and generated bytes                             |

Cloudflare Durable Object point-in-time recovery can inspect or restore one object, not the whole
installation. The product exposes owner-only recovery-point inspection for the active event, but
does not expose restore as a normal UI or agent action.

A safe restore procedure must capture an export first, record an undo point, restore only with
explicit authority, restart the object session, reconcile access and files, and verify the event
before reopening writes. See [Operations](https://forge.smol.ai/andheller/programkit/blob/main/OPERATIONS.md) for the canonical runbook boundary.

## Departure and portability

Download the logical event export and export R2 objects with a manifest relating object keys to
asset records. The logical export intentionally does not contain raw account credentials, API key
secrets, or file bytes.

The domain engine is provider-independent, but Cloudflare is the only maintained host assembly. A
different host must supply equivalent transactional storage, identity, files, jobs, email,
authorization, tests, and operational docs.

## Monitoring checklist

At minimum, watch:

- Worker errors and latency;
- Durable Object exceptions and alarms;
- login and password failure rate;
- R2 upload, download, cleanup, and storage usage;
- email pending, retry, and failed counts;
- API-key errors and unexpected last-used activity;
- public form and agenda availability; and
- deployment and migration outcomes.

The repository enables Cloudflare Worker observability, but it does not yet ship a complete
production alerting or status system. Add thresholds, notification ownership, and incident
procedures for your environment.

## Before a public launch

Complete the production requirements in [Security](https://forge.smol.ai/andheller/programkit/blob/main/SECURITY.md), then perform a fresh-account
rehearsal across organizer, submitter, reviewer, speaker, attendee, API, MCP, email, and file flows.
