انتقل إلى المحتوى

Known limitations

An honest list of what the current code does not do, so nobody is surprised.

Security

  • No rate limiting. Sign-in, password reset, share-link unlock and invitation endpoints do not limit attempts. The only throttles are on sign-up codes (30 s between codes, 5 attempts per code). Put a rate limit in front, for example in the Cloudflare Worker, before opening an instance to the public at scale.
  • Forgot password says whether an email exists. This was chosen for clarity, but it lets someone check whether an address has an account.
  • Invitation and share tokens are stored as is, unlike session and reset tokens, which are hashed.
  • Password-protected share links: the captions file and view reporting for a share link do not check the password. The video itself and its comments do.
  • Expired sessions are no longer accepted, but their rows are not cleaned up from the database.

Tooling

  • scripts/smoke.sh and scripts/seed-demo.sh stop at the account step, because sign-up now needs the emailed code and the scripts do not send it yet.

Features

  • Workspace-wide visibility (org) and share-link passwords, expiry and comment switches exist in the API, but the interface does not offer them.
  • Deleting a workspace and transferring ownership are not implemented.
  • Video replies have no countdown, pause, trim or blur. The Reply with video button is also shown to viewers, who cannot post one.
  • Captions on the share page: the server serves them, but the share page does not show them yet.
  • Chapters cannot be deleted from the interface (the API can).
  • Tours are remembered per browser.
  • The AI "Test" button checks text completion only, not audio.
  • VISTILLA_TRANSCRIBE_LANGUAGE and VISTILLA_SUMMARY_MAX_TOKENS are read but not applied.
  • Failed AI jobs are not retried automatically: press Try again.

Hosting (free tier)

  • Storage: the free Backblaze B2 tier holds 10 GB, about ten two-hour meetings at the recorder's bitrate. The library's storage meter shows how full it is, but nothing stops an upload when it is full; the bucket then refuses it.
  • Long recordings are slow to process on the free server (a fraction of one CPU). A two-hour meeting can take a while to become seekable, and its transcript needs about 120 AI requests.
  • Cold starts: the free Render service can take a little while to wake. The Worker shows a "Vistilla is starting" page meanwhile, and its 10-minute ping keeps it awake most of the time.
  • Backblaze's free download allowance is 1 GB a day. Downloads go through the Cloudflare Worker, which B2 does not charge for; anything that reaches B2 directly (the database restore at start-up) still counts. If the allowance is used up, the site starts from the second bucket (below) when there is one, else not until midnight UTC.
  • Backblaze's free daily transaction caps (reads and listings) can run out on a busy day, for example after dozens of deploys (each start reads the database replica) or heavy testing. B2 then answers "Transaction cap exceeded": videos stop playing and every new deploy fails at start-up, while the running server stays live. Everything returns at midnight UTC; a deploy that failed meanwhile has to be started again. To keep this rare, and harmless when it happens:
    • Fewer requests. Download links stay the same for an hour, so the browser keeps what it fetched (Cache-Control from the Worker) and the app keeps up to 400 MB of watched video on the phone. Posters are read from the bucket once per server start, then from its disk. Litestream looks for old pieces once an hour. Pushes that change only android/, worker/ or scripts/ do not redeploy (Render build filter).
    • Deploys do not read the bucket. A new server takes the database from the running one (see Deployment); the bucket's copy is read only when no server is running. A deploy costs about 16 listings instead of about 45 and a read per backup piece.
    • A second copy (VISTILLA_MIRROR_S3_*, best a second free Backblaze account): every recording and picture is copied there in the background, and the database every 6 hours and as the server stops. When the first bucket refuses, pictures are read from the copy, video links point at it, and the players ask for it (?from=mirror) before showing "Back soon". A start while the first bucket refuses runs from the second one, backed up there, instead of waiting for midnight UTC (see Deployment). A video uploaded after the first bucket started refusing is copied only after the reset, so until then it waits.
    • A guard when it happens. The Worker turns B2's refusal into a 429 with the reset time; the web and app players then say "Videos are resting until …" and load by themselves after it, instead of retrying. Background jobs (index, pauses, transcripts) wait, unmarked, until a few minutes past midnight UTC and then carry on; summaries go on, as they do not read the bucket.
  • A crash (not a deploy) can lose at most the last second of changes: Litestream ships them to the bucket every second, and that copy is what a server starting with no other server running restores. The one exception: a crash on a day the first bucket then refuses at start-up. The new server starts from the second bucket's plain copy, which can be up to 6 hours behind, and those hours stay only in the first bucket.
  • The server's temporary disk is 2 GB, and the host stops the server when it overflows. A recording over 1.5 GB (about 750 MB if trimmed) is therefore not rewritten by ffmpeg and its trim is skipped; a WebM still gets its index, added as it streams with nothing on disk. Jobs read recordings from the bucket instead of copying them.
  • Unfinished recordings (the recorder page crashed or lost the server mid-upload) are kept for 7 days, so the owner can press Publish what arrived; then they are thrown away.
  • Email volume through the Apps Script relay is limited to about 100 a day.
  • SQLite and one instance: the design expects a single server process writing to the database. Scaling out means a different database setup.