Files
nroxy/docs/plan/system-plan.md
sirily 55472de23d chore: remove MVP positioning and align plan defaults (#15)
## Summary
- remove MVP wording from repository docs and guidance
- rename the system plan document and update references to it
- align the default subscription plan code/name with product wording
- document hard subscription expiry with no grace period

## Verification
- docker build -f infra/docker/web.Dockerfile .
- docker build -f infra/docker/migrate.Dockerfile .

Co-authored-by: sirily <sirily@git.shararam.party>
Reviewed-on: #15
2026-03-10 15:01:06 +03:00

105 lines
4.3 KiB
Markdown

# System Plan
## Summary
Build `nproxy`, a B2C web product for image generation through external model APIs. The first model is `nano_banana`. Users register with `email + password`, pay a monthly crypto subscription, receive a monthly request limit, and use a chat-style interface for `text-to-image` and `image-to-image` generation.
The service hides provider-key failures behind a routed key pool. A user request is attempted against one provider key at a time. Retryable failures move execution to the next eligible key. The user sees an error only after all eligible keys have been exhausted or the request fails for a terminal user-caused reason.
## Confirmed product decisions
- One B2C website.
- One monthly subscription plan.
- Crypto checkout through a payment processor.
- Manual renewal.
- Text-to-image and image-to-image.
- User-facing synchronous experience implemented with polling over background execution.
- Approximate quota buckets only: `100/80/60/40/20/0`.
- Storage in S3-compatible object storage.
- One VPS deployment with Docker Compose.
- Web admin plus Telegram admin bot.
- Telegram admin onboarding through pairing on the server console.
- Multiple provider API keys with round-robin routing, cooldown, balance tracking, optional per-key proxy, and transparent failover.
## Core product surfaces
### Public web
- landing page
- register / login / password reset
- dashboard with subscription state and approximate quota
- chat UI
- billing / checkout pages
### Admin surfaces
- web admin for users, subscriptions, payments, generations, provider keys, proxies, and health
- Telegram bot for alerts and low-friction admin actions
- CLI for server-side operational commands, including Telegram pairing
## Main backend domains
- auth
- billing
- subscriptions
- quota ledger
- conversations and generations
- provider routing
- provider key pool health
- asset storage
- admin audit
- notifications
## Billing rules
- One active plan.
- Access ends immediately when `currentPeriodEnd` is reached. Warnings may be sent beforehand, but there is no grace period after expiry.
- Each user has an individual billing cycle based on successful activation timestamp.
- Limit resets on each successful cycle activation.
- One successful generation consumes one request.
- Failed generations do not consume quota.
## Quota display contract
Backend tracks exact usage. Normal users see only an approximate bucket:
- `81-100%` remaining -> `100%`
- `61-80%` remaining -> `80%`
- `41-60%` remaining -> `60%`
- `21-40%` remaining -> `40%`
- `1-20%` remaining -> `20%`
- `0%` remaining -> `0%`
## Generation controls
- mode: `text_to_image` or `image_to_image`
- resolution preset
- batch size
- image strength for `image_to_image`
## Key pool behavior
- Start from the next `active` key by round robin.
- Use the key-specific proxy first if configured.
- If the proxy path fails with a transport error, retry the same key directly.
- Retry on the next key only for retryable failures: network, timeout, provider `5xx`.
- Do not retry on the next key for validation, policy, or other user-caused `4xx` errors.
- Move a key to `cooldown` on retryable failures.
- Default cooldown is `5 minutes`.
- After more than `10` consecutive retryable failures across cooldown recoveries, move the key to `manual_review`.
- Move a key to `out_of_funds` when the provider balance API or provider response shows insufficient funds.
- `out_of_funds` and `manual_review` keys return to service only through a manual admin action.
## Telegram pairing
1. A Telegram user opens the bot.
2. If the user is not in the allowlist, the bot generates a short pairing code and stores a pending pairing record.
3. The bot tells the user to run `nproxy pair <code>` on the server.
4. The server-side CLI confirms the target user and adds the Telegram ID to the allowlist.
5. The pairing record is marked complete and the user gains bot access.
## Deployment target
Single VPS with Docker Compose, expected services:
- `web`
- `worker`
- `bot`
- `postgres`
- `caddy` or `nginx`
- optional `minio` when object storage is self-hosted
## Optional extensions
These are not current commitments. Consider them only if user demand, operational need, and product scale justify the added complexity:
- more image providers
- more billing methods
- more subscription plans
- internal balance wallet
- recurring billing if the payment processor supports it natively