Commit Graph
25 Commits
Author SHA1 Message Date
Jasper Van c85e60f200 fix(analytics): enforce trustworthy offline statistics (#510)
* fix(analytics): enforce trustworthy offline statistics

Separate immutable counters from point-in-time snapshots, expose incomplete coverage instead of synthetic zeroes, and keep browser analytics result-only.

Restore finite Free quota baselines, fail closed for invalid storage quota, reconcile traffic reports fairly, and add production-safe backfill and data-quality diagnostics.

* fix(analytics): preserve global backfill totals

Group generated hourly backfill rows by their projected values so SQLite cannot resolve output aliases to source organization columns and overwrite cross-organization totals.
2026-07-20 10:23:22 -04:00
saltbo 60f8f64481 refactor(analytics): enforce offline result boundaries
Build versioned UTC hourly rollups, validate analytics facts, and keep dashboard requests result-only with explicit coverage semantics.

Move derived metrics to the server and simplify the admin dashboard around one reconcilable UTC range without export.
2026-07-18 01:58:34 -04:00
Jasper Van 8bd1e55b5c refactor(analytics): replace daily stats with hourly rollups (#505)
* refactor(analytics): replace daily stats with hourly rollups

* fix(analytics): merge hourly inventory sources

* test(analytics): cover rollup failure boundaries

* test(analytics): verify growth dashboard metrics

* test(analytics): cover historical rollup reads

* test(analytics): verify hourly dashboard dimensions

* test(analytics): cover remaining metric boundaries

* test(analytics): cover backfill SQL parsing
2026-07-10 13:26:27 -04:00
saltbo ccdab7814d docs: update roadmap for analytics cli and sync 2026-07-08 23:24:31 -04:00
agent-kanban-local[bot]andAlex Chen 00f48cf355 feat(avatars): host avatars + team logos on Cloud via SDK 2.4.0; remove public-bucket mode (#467)
* feat(avatars): host avatars + team logos on Cloud via SDK 2.4.0; remove public-bucket mode

Host user avatars and org logos on the ZPan Cloud avatar service
(zpan-cloud-sdk ^2.4.0) instead of a public S3/R2 bucket, then remove the
now-dead storages.mode / public-bucket concept entirely (#456 parts 2-3).

- image-upload gateway: upload/delete via SDK uploadAvatar/deleteAvatar against
  a bound Cloud client; validate mime (AVATAR_CONTENT_TYPES) + size
  (MAX_AVATAR_BYTES) before the call; map cloud error codes to 400/403/413/500;
  unbound instance returns 503 cloud_required (delete is a best-effort no-op).
- licensing-cloud: createAvatarUploadClient builds the client with a plain-object
  bearer header so both the image content-type and Authorization survive hono's
  per-request header merge (a Headers instance would be dropped).
- drop storages.mode (migration via drizzle-kit), StorageRepo.select() no longer
  takes a mode, remove StorageMode / Storage.mode / mode schema+audit+UI+i18n and
  the PUBLIC_IMAGES bucket + PUBLIC_IMAGES_URL wiring.

Agent-Profile: https://agent-kanban.dev/agents/f759c704c282d88a

* ci(deploy): drop dead PUBLIC_IMAGES R2 provisioning from CF deploy

The Cloud avatar migration removed the PUBLIC_IMAGES binding from
wrangler.toml, so the deploy workflow's R2 public-images steps are dead and
must go too — otherwise every CF deploy keeps re-provisioning a public-read
zpan-public-images bucket (the footgun #456 eliminates) and sets an unused
PUBLIC_IMAGES_URL secret. Removes the bucket-create, managed-public-URL, and
secret steps (steps.r2 was only consumed by the secret step). Also drops a
stale storage-modes line from the v2.0 roadmap.

Agent-Profile: https://agent-kanban.dev/agents/f759c704c282d88a

---------

Co-authored-by: Alex Chen <alex-chen@mails.agent-kanban.dev>
2026-06-20 00:16:07 -04:00
saltbo d693837150 chore: update default branch references from master to main 2026-06-12 12:45:39 -04:00
Jasper Van 650f209fe8 docs: clarify cloud credit billing boundaries
Clarify ZPAN's Cloud Credits boundaries and keep gift-card creation on the Credits-only contract.
2026-06-02 03:41:07 -04:00
saltbo 9d13ee7055 docs(roadmap): revise v2.7 download planning 2026-05-11 01:08:20 -04:00
saltbo 06c7be910b docs(roadmap): update v2.7 file workflow plan 2026-05-11 00:37:27 -04:00
Jasper Van 3b2a2b03bf test: document metered storage plan flow (#386)
* test: document metered storage plan flow

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5

* test: align subscription entitlement lifecycle

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5
2026-05-08 21:42:40 -04:00
Jasper Van 11ab430493 refactor(quota-store): unify orders and gift cards
* refactor(quota-store): unify orders and gift cards

* test(quota-store): cover helper paths

* test(quota-store): cover webhook idempotency

* test(quota-store): cover cloud response normalization
2026-05-07 09:03:55 -04:00
Jasper Van 5632cbbc83 fix: use pro binding auth for quota store (#367)
* fix: use pro binding auth for quota store

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5

* fix: align quota store event token audience

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5

* fix: match cloud delivery event audience contract

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5
2026-05-06 00:29:48 -04:00
Jasper Van 8f6e4c2ff3 Fix quota store Cloud binding contract (#366)
* fix(quota-store): use Pro binding for Cloud store auth

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5

* fix(quota-store): align Cloud store binding contract

Agent-Profile: https://agent-kanban.dev/agents/1dc839c09b5ee5e5
2026-05-05 22:32:40 -04:00
Jasper Van 05b14a4991 docs: verify pro quota store release notes (#364)
Agent-Profile: https://agent-kanban.dev/agents/a318237412dd8b98
2026-05-05 17:13:54 -04:00
saltbo d7f1ceb6bc feat(licensing): adjust free plan limits 2026-04-27 20:41:46 -04:00
saltboandClaude Opus 4.7 5de2100435 docs(roadmap): update v2.6 cloud dependency to v1.0
zpan-cloud renumbered from v0.x to v1.x (SemVer: first stable
= 1.0). v2.6 Pro Launch now depends on cloud v1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 21:36:07 -04:00
saltboandClaude Opus 4.7 751b09366d docs(roadmap): restructure v2.6–v2.10 around Pro Launch
- v2.6 becomes Pro Launch: cloud-account binding activation,
  Ed25519 entitlement certificates, white-label as first Pro
  feature, retroactive Pro gates (open registration, team count
  ≤3, per-team storage quota)
- v2.7 becomes Pro Operator: audit log, webhooks, anti-abuse
  stack for the Pro-gated open registration mode
- v2.8 becomes Pro Analytics & Identity: analytics dashboard,
  multi-IdP SSO + SAML, LDAP / SCIM
- Original Backup (v2.6) content moved to v2.9; Sync & Desktop
  (v2.7) content moved to new v2.10
- Managed Cloud Services extracted to a separate closed-source
  zpan-cloud repo (content moderation, server-side processing,
  managed custom domains)
- Community vs Pro split rewritten around the operator rule
  ("features that help you use ZPan are free; features that
  help you operate ZPan for others are Pro")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 21:29:54 -04:00
saltboandClaude Opus 4.7 5bd29b5e8c docs(roadmap): refocus v2.5 on multi-platform deployment via Turso
v2.5 originally covered branding polish. Shift it to unlock
multi-platform deployment — seven first-class targets (CF Workers,
Docker, AWS Lambda, Vercel, Netlify, Azure Functions, Google Cloud
Run) using Turso libSQL as the universal non-CF database. Zero
SQLite-dialect work, generous free tier, HTTP protocol sidesteps
serverless connection-pool issues.

GitHub Actions workflows drive each deploy, mirroring the existing
CF deploy.yml pattern (self-healing resources, auto-generated
secrets, upstream release tracking). Object storage credentials
stay in the admin UI storages table, not GitHub Secrets.

Site branding (custom logo, favicon) moves to v2.8 as a managed-
only white-label feature. User avatar upload remains in v2.5 as
the sole carry-over from the original scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:55:05 -04:00
saltboandCopilot b62ff49469 docs: update v2.4 roadmap and specifications
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 10:41:24 -04:00
3e6d3ee63b feat: v2.4.0 T5 — /api/ihost/config + Cloudflare for SaaS integration (#316)
* feat: add /api/ihost/config endpoint with Cloudflare for SaaS integration

- Add CfCustomHostnamesClient service (thin CF API wrapper; no-op when CF env vars absent)
- Add /api/ihost/config route (GET/PUT/DELETE) following email-config pattern
- GET lazily refreshes domain verification from CF; PUT upserts config, registers/deregisters CF hostnames; DELETE best-effort CF cleanup + row removal
- PUT rejects enabled=false (must use DELETE); validates customDomain hostname format; validates refererAllowlist entries as URL origins; catches unique constraint → 409
- Add putIhostConfigSchema and IhostConfigResponse to shared schemas/types
- Mount route in app.ts under /api/ihost/config
- Add image_hosting_configs and image_hostings tables to test setup SQL
- Add 22 integration tests covering all acceptance criteria
- Update v2.4.md roadmap with config API notes; add docs/ihost-custom-domain-node.md

Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f

* fix(ihost-config): restrict PUT/DELETE to owner role, add CF client unit tests, fix CodeQL URL check

- Change requireTeamRole('editor') → requireTeamRole('owner') on PUT and DELETE (spec requires owner/admin only)
- Add explicit editor-role 403 tests for PUT and DELETE
- Add server/services/cf-custom-hostnames.test.ts: 16 unit tests covering register/getStatus/delete success, 409/4xx/network errors, no-op behavior, createCfClient factory
- Add integration tests: GET domainStatus=verified, domainStatus=none, refererAllowlist JSON parsing, CF lazy verification active/pending paths, dnsInstructions CNAME vs manual, APP_HOST rejection, CF register on PUT, CF delete+register on domain change, CF 409 from register, clear refererAllowlist, DELETE best-effort CF cleanup (success + fail-graceful)
- Replace .includes('cloudflare.com') with new URL(url).host === 'api.cloudflare.com' to fix CodeQL CWE-20 incomplete URL substring sanitization
- Make createTestApp accept optional envOverrides to enable CF-configured integration tests

Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f

* test(ihost-config): add coverage for uncovered error paths to reach 95%

Add 4 targeted integration tests that cover the previously-uncovered
branches in server/routes/ihost-config.ts:
- PUT INSERT: CF register() throws non-CfConflict error → propagates
- PUT UPDATE: CF delete() fails (best-effort console.warn) → request succeeds
- PUT UPDATE: CF register() throws non-CfConflict error → propagates
- PUT UPDATE: DB unique constraint on UPDATE → 409 (org2 steals org1 domain)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 04:00:17 -04:00
saltboandClaude Opus 4.6 3b80eff413 feat: migrate from CF Pages to Workers with one-click deploy button
- Replace Pages Functions with Workers entry (`workers/bootstrap.ts`)
- Add Deploy to Cloudflare button in README
- Integrate `@cloudflare/vite-plugin` for CF dev with HMR
- Integrate `@hono/vite-dev-server` for Node dev with HMR
- `npm run dev` now defaults to CF Workers mode
- Add `run_worker_first = ["/api/*"]` so static assets stay free
- Extract shared Node bootstrap (`server/bootstrap.ts`) for reuse
- Update all docs from Pages to Workers references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:40:15 -04:00
saltboandClaude Opus 4.6 8dcce94f7c docs: reorder roadmap — prioritize auth and teams over image bed
Move Auth & Access (social login, OIDC, invite codes) to v2.1 and Teams
to v2.2, shifting Sharing, Image Bed, and Branding to v2.3–v2.5. Remove
completed items (Drizzle migration, SVAR replacement) from Image Bed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:49:31 -04:00
saltboandClaude Opus 4.6 2e483109c9 docs: add Drizzle query builder migration to v2.1 roadmap
48 raw SQL calls bypass Drizzle schema — no type safety on queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:55:05 -04:00
saltboandClaude Opus 4.6 26f01687a0 docs: add custom file manager to v2.1 roadmap
Replace SVAR with shadcn-based file manager due to theming conflicts,
upload event bus bypass, and path-based ID model mismatch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:19:26 -04:00
saltboandClaude Opus 4.6 b817cab2c1 feat: ZPan v2.0 roadmap, architecture, and repo reset
Remove the Go v1 codebase (preserved in the v1 branch) and establish
the foundation for v2 — a complete rewrite in TypeScript (server) and
Rust (CLI/desktop). This commit includes the product roadmap (v2.0–v2.9),
technical architecture document, and updated project documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 20:57:15 -04:00