Skip to content

Add 12h price/visibility change delay for public community endpoints (#13800) - #1

Open
aikhusus2025-ctrl wants to merge 123 commits into
mainfrom
add-cli-earnings
Open

aikhusus2025-ctrl wants to merge 123 commits into
mainfrom
add-cli-earnings

Conversation

@aikhusus2025-ctrl

Copy link
Copy Markdown
Owner

Implements the price/visibility change delay for public community endpoints (quest pollinations#13800).

Changes:

  • shared/db/better-auth.ts: add pendingPayload, pendingVisibility, and pendingAt columns to the community-endpoint model so price/visibility changes to a public model are queued for 12 hours before they become effective.
  • enter.pollinations.ai/src/routes/community-endpoints.ts: queue price/visibility updates (including transitions to public) into the pending columns instead of applying them immediately; the effective value flips once the deadline passes.
  • enter.pollinations.ai/src/routes/community-endpoints/presenter.ts: expose the pending/effective values so the UI shows the scheduled change.
  • gen.pollinations.ai/src/community-models.ts: apply the effective (post-deadline) values when presenting public models.

Gives consumers 12 hours of notice before a public model's price or public visibility changes.

aikhusus2025-ctrl and others added 30 commits August 19, 2026 18:51
…linations#13531)

* Round balances using POLLEN_BILLING_PRECISION

* Use POLLEN_BILLING_PRECISION for balance updates

Update balance calculation to use rounding with defined precision.

* Add ledger precision tests for quest rewards

This test verifies that quest rewards and usage charges maintain 8-decimal precision in the ledger.

* Refactor update statement for bucket balance

* fix(billing): round the two Stripe credit paths too

The PR rounds every deduction and reward claim to ledger precision but
leaves both pack-purchase credits unrounded, so any checkout or auto
top-up reintroduces the float drift it just removed.

- stripe-webhooks.ts: checkout session credit
- stripe-billing.ts: auto top-up invoice credit

Forward-only, like the rest of the PR — existing dirty balances such as
10.316053619999998 are not backfilled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkpGbmYzzesyaGNxewSCyy

---------

Co-authored-by: voodoohop <t.haferlach@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: voodoohop <thomash@pollinations.ai>
* feat: add account settings

* fix: preserve deleted account reward records

* fix: hard-delete accounts without resetting quests

* fix: secure account deletion and quest history

* fix: align account deletion legal notice

* fix: refine signed-out navigation

* fix: close mobile drawer from account menu

* refactor: dedup quest rewards on the GitHub id in the key alone

- Adds shared rewardKey(); quest checks, admin grants, and coupon redemption
  now build one key shape instead of three hand-rolled variants
- Drops rewards.github_id — the key already carries the identity; migration
  0050 re-keys quest:{id}:user:{userId} rows to quest:{id}:github:{githubId}
- Makes user.github_id unique so one GitHub identity cannot hold two accounts
- Fixes grants and coupons still keying on the account id, which let a user
  delete, re-signup, and redeem the same coupon twice
- Collapses perSubject into perUser (byte-identical key) and drops the
  Connected accounts panel — GitHub is the only sign-in

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: keep migration 0050 as drizzle-kit output plus the backfill

- Restores drizzle-kit's own statement order; the only hand-written part is
  the INSERT, which re-keys per-person rewards (drizzle generates a plain
  column copy and never emits data migrations)
- Qualifies the select as `r`.`id`, ambiguous once the user join is added
- drizzle-kit generate reports no schema changes: snapshot and journal match
  shared/db/better-auth.ts

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: split the reward re-key into a drizzle custom migration

- 0050 is `drizzle-kit generate --custom`: one UPDATE that re-keys per-person
  rewards from the account id to the GitHub id
- 0051 is `drizzle-kit generate` verbatim, no hand edits — it drops
  rewards.github_id and adds the unique index on user.github_id
- Re-keying first means the old unique index on idempotency_key is still in
  place, so a collision aborts before anything is dropped or rebuilt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: trim redundant markup from the account page

- Drops the "profile details come from GitHub" footnote, which restates the
  @username link rendered above it
- Drops the class-less <div> wrapping each Section's children; Section framed
  already lays children out in a flex column with gap-5, so the inner mt-4/mt-5
  spacing goes with it
- Uses user.image directly instead of an `|| ""` local
- Drops text-[10px] from the sign-in consent line; size="micro" is already 10px

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat: key quest rewards on the GitHub user id

- Adds shared rewardKey(); quest checks and admin grants build one key shape
  instead of hand-rolled variants
- Drops rewards.github_id — the key already carries the identity. 0050
  (drizzle --custom) re-keys quest:{id}:user:{userId} rows to
  quest:{id}:github:{githubId}; 0051 (drizzle generate, verbatim) drops the
  column and makes user_id nullable so rewards outlive the account
- Makes user.github_id unique — one GitHub identity cannot hold two accounts
- Collapses the perSubject quest scope into perUser; it emitted a
  byte-identical key
- Quest status resolves rewards left by a previous account with the same
  identity, and the leaderboard skips rewards whose account is gone

Verified against production data: 19,242 rewards, 18,889 re-keyed, 0 duplicate
GitHub ids, 0 accounts without one, 0 key collisions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore: drop package-lock churn

- Reverts the reordering npm install produced in a fresh worktree; no
  dependency change

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: drop the orphan-reward lookup from quest status

- Reverts account.ts to the plain userId filter, matching /quests/rewards
- A re-registered account now sees the quest as open; the unique key still
  swallows the insert, so it cannot be earned twice

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: assert quest status stays open for a replacement account

- Follows the pollinations#13564 revert: quest status is scoped to the account's own
  rewards again
- Re-earning is still a no-op, asserted by the recordRewards check above

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: show retained quests as already earned

* refactor: reuse claimed UI for retained quests

* revert: drop the retained-quest display

A user who deletes their account, re-registers, and then goes looking for
quests is not worth code in three files. The unique reward key from pollinations#13564
already stops them re-earning anything; all this added was a nicer label on
the card they can no longer complete.

- Reverts the widened reward queries in /account/quests and /quests/rewards
  to the plain userId filter
- Drops previouslyEarnedQuestIds from the API and the frontend state that
  threaded it
- The replacement account sees the quest as open; earning it again is a
  silent no-op, as asserted by the recordRewards check in the test

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: voodoohop <t.haferlach@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Record how the MCP Cloudflare Worker at mcp.pollinations.ai deploys:

- deploy-applications.yml triggers on production branch pushes
- discover.cjs matches apps/mcp via deploy.json watch globs
- Path filters cover both apps/** and packages/mcp/**
- Production gating via guard-production-source.yml
- No staging MCP deploy (thin proxy; staging at gateway level)

Fixes pollinations#13408

Co-authored-by: Karan Ray <karanray06@users.noreply.github.com>
Co-authored-by: voodoohop <thomash@pollinations.ai>
…ions#13588)

A 402 means the caller had no Pollen left: the request is rejected at the
balance check, before any provider runs. It is billed nothing and generates
nothing, but it carries a user_id, so it counted as an active user and as a
request. Last week that was 3.1M requests from 3,507 users.

The effect was not cosmetic. Reported WAU has been flat for ten weeks —
6,798 to 6,859 — while users who actually got a response fell 5,716 to
3,352. The dashboard showed a stable user base through a 41% decline.

- WAU, total requests, text/image requests, community user share and BYOP
  user share now count served users only.
- WAU and BYOP user % cycle to the raw figure, so nothing is lost.
- New "Turned away" row: users whose every request hit the Pollen wall.
- Per-user metrics (Tokens/user, ARPA, Purchase rate) divide by served WAU,
  which roughly doubles Tokens/user.
- Fixes text_requests and image_requests, which matched event_type 'text'
  and 'image' where the values are 'generate.text' and 'generate.image',
  and so had always returned 0.

Pipe changes are additive; the only consumer is this dashboard.
* fix: keep tracking alive after malformed SSE chunks

* fix: simplify malformed SSE tracking

---------

Co-authored-by: voodoohop <t.haferlach@gmail.com>
Co-authored-by: voodoohop <thomash@pollinations.ai>
…ations#13523)

* fix(fallback): hide private-target oracles and leaky metadata

Keep fallbackTarget non-enumerable so cached JSON never ships it.
Collapse other-owner private/deactivated fallback 400s into the
same "does not exist" as a missing row. Do not fail over an
edits request onto a generations-only target.

Fixes pollinations#12890

* fix(enter): type fallback inputModalities as ModelInputModality

CI typecheck failed: readonly string[] is not assignable to the
normalizeCommunityEndpointInputModalities parameter.

---------

Co-authored-by: voodoohop <thomash@pollinations.ai>
…ollinations#13522)

* fix(gen): prefer defined flat-rate prices in preflight

Tinybird avg_cost_usd was blocking community image models whose
defined completionImagePrice is a few cents. Use the model
definition for flat-rate / per-image models and keep Tinybird only
for token-priced ones.

Fixes pollinations#12747

* fix(stats): median Tinybird cost and drop poisoned preflight averages

The 33.34 estimate was the 7-day mean of rows that billed
completionImagePrice * OpenAI output_tokens (~0.01 * 3334). Request-priced
community images now log 1 unit, but the mean stays wrong until those rows
age out, and token-priced models have the same outlier problem.

Use medianIf in public_model_stats, and ignore Tinybird in preflight only
when it is missing or >10x the defined per-request price.

* style: apply biome wrap and compact array for preflight files

CI failed biome check --write on model-stats.ts and byop-markup.test.ts.

---------

Co-authored-by: voodoohop <thomash@pollinations.ai>
Co-authored-by: pollinations-ai[bot] <pollinations-ai[bot]@users.noreply.github.com>
Co-authored-by: pollinations-ai[bot] <pollinations-ai[bot]@users.noreply.github.com>
* feat: add Azure GPT transcription models

* test: update transcription pricing snapshot
Fixes pollinations#13559

Co-authored-by: pollinations-ai[bot] <247793354+pollinations-ai[bot]@users.noreply.github.com>
Co-authored-by: MoronDe <112860827+MoronDe@users.noreply.github.com>
…ns#13527)

* fix: keep hidden community models callable

* fix: codify community monitor hide policy

* refactor: unify community model hidden state

* fix: use hidden state in community monitor
…ations#13593)

* fix(econ): stop booking community sale price as provider cost

Community total_cost equals the sale price, but we never pay an
upstream — the 75% owner payout is already in model_paid. Counting
both made every community row show margin -0.75 per 1.0 sold.

Zero community cost in op_pollen_populate, ignore it in the
economics reader (covers historical rows), and stop the community
connector from mirroring that meter into op_cloud.

Fixes pollinations#12895

* fix(econ): normalize community costs at source

* chore(kpi): invalidate Tinybird cache

---------

Co-authored-by: voodoohop <t.haferlach@gmail.com>
Co-authored-by: voodoohop <thomash@pollinations.ai>
Fixes pollinations#13598

Co-authored-by: pollinations-ai[bot] <247793354+pollinations-ai[bot]@users.noreply.github.com>
Co-authored-by: momokula123 <227260546+momokula123@users.noreply.github.com>
Co-authored-by: pollinations-ai[bot] <pollinations-ai[bot]@users.noreply.github.com>
…13637)

- Folds deploy-enter/gen/media-cloudflare.yml into deploy-cloudflare-production.yml: one `migrate` job gates three parallel deploy jobs, so ordering is deterministic and the cross-workflow queue gap (2-6 min) collapses to the deploy step.
- Previously all three workflows applied the same D1 migrations in arbitrary order; whichever ran first moved the schema while the other workers served old code.
- `dorny/paths-filter@v3` pinned with `base: ${{ github.ref }}` - without it the action diffs merge-base(main, production)..production, empty after a promotion, so every filter reports false.
- `migrate` gated on at least one service deploying, making "migrations applied, no worker updated" unreachable.
- Docs regeneration gated on the run's `deploy-gen` job rather than the aggregate conclusion.
- Runbooks updated for the removed workflow names.
…13641)

- Hoists gen's Test/Typecheck into a `test-gen` job that gates `migrate`, leaving `deploy-gen` as install + deploy (~30s with the npm cache).
- Closes the window where the deployed gen queries a post-migration schema: `loadGenerationModelRegistry` has no try/catch, so a dropped column fails the whole registry including STATIC_ENTRIES, 500ing all image and text traffic. Measured gap was 3m24s; now inside REGISTRY_TTL_MS = 60_000.
- A red gen test now blocks the migration rather than trailing it.
- `migrate` uses `!cancelled()` so a skipped `test-gen` does not skip every deploy.
…ollinations#13643)

Every request that resolves a model goes through getGenerationModelRegistry,
and the community-model D1 query it depends on had no error handling. A single
failing SELECT there — most realistically schema skew, where a migration lands
before the Worker that understands it — turned a community-catalog problem into
a total gen outage: /v1/models, /image/models and every generation request 500.

The 60s registry cache does not cover this. It is per-isolate, so cold isolates
miss it and load the registry immediately; under production traffic new isolates
start continuously.

- Catch the community query failure and build the registry from static entries
- Cache a degraded registry for 5s, not 60s, so recovery is fast
- Test asserts static models still resolve when D1 reports a missing column

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…#13623)

* feat(listings): one typed listing table — type + payload envelope

A community listing now says what it is (`type`) and carries only what that
kind has (`payload`). The fields a kind does not have have nowhere to live, so
the rules that used to reject them field by field are gone.

- `community_endpoint.type` ∈ proxy | prompt_agent | hosted_agent, plus a
  `payload` JSON column whose shape the type selects. Migration 0052 adds both
  and backfills every row from the columns they replace.
- Runtime union is `kind: "proxy" | "prompt_agent" | "hosted_agent"`; only a
  proxy has a `bearerTokenCiphertext`, only a prompt agent has an `agentId`.
  `isDelegatingEndpoint` is `kind !== "proxy"`.
- Create is a Zod discriminated union on `type` instead of a superRefine with a
  four-entry `agentRejections` array. An agent listing sending a price, a
  credential, a fallback list, or an RPM cap is an unrecognized key, so a later
  feature cannot forget to reject it. `type` is inferred from `agentId` for
  callers written before it existed.
- gen reads `type` + `payload` and parses per arm, so each branch is narrowed
  to the shape its type declares. Legacy columns are still written by Enter and
  the payload is derived from them, so the two cannot drift; a follow-up drops
  them once gen ships.
- Frontend agent listings are identity only — the model-catalog fetch that
  existed to fill inherited `inputModalities` is gone.

Deploy Enter first: it writes both, and gen only starts reading the payload
after its own deploy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(listings): assert the 0052 backfill types rows and packs payloads

Runs the real migration SQL against a scratch table, the pattern pollinations#13529 used
for its kind backfill, extended to the payload half.

- Both agent kinds, the inert image delegation flag, and two proxy shapes
- Exact payloads: a hosted agent keeps a target and drops its credential, a
  prompt agent keeps nothing, a proxy keeps its nine prices in the right slots
- Null input_modalities and fallback_model_ids become null and [], not literal
  nulls the reader would have to re-normalize

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: unify community listings and agents

* fix: simplify typed listing updates

* fix: address listing envelope review findings

* fix(test): drop the agentTable assertion left behind by the envelope cutover

The PR removes the `agent as agentTable` import and the agent fixture insert
but keeps `expect(await db.select().from(agentTable)).toHaveLength(0)`, so the
test dies with `ReferenceError: agentTable is not defined`. 0053 does
`DROP TABLE agent`, so the assertion has nothing left to check.

Not caught by CI: enter's suite does not run there, and enter/tsconfig.json
excludes test/** from typecheck.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
voodoohop and others added 9 commits August 24, 2026 08:06
* feat: proxy trusted MCP servers through Gen

* feat: accept public FFmpeg input URLs

* feat: route registered MCP servers through Gen

* refactor: settle MCP usage before telemetry

* refactor: remove unused FFmpeg lifecycle routes

* refactor: keep FFmpeg constants with its Worker

* docs: link hosted MCP registry

* refactor: use default stateless MCP transport

* refactor: route MCP servers from registry

* feat: add private media upload entrypoint

* feat: add FFmpeg MCP worker

* fix: simplify registered MCP tool names

* fix: align MCP proxy billing tracking

* ci: deploy MCP workers before Gen bindings

* refactor: share MCP usage receipts

* fix: redeploy FFmpeg on receipt changes

* ci: serialize MCP production rollout

* refactor(mcp): separate registry from server implementations

* fix: show environment-specific MCP endpoints

* fix: simplify MCP agent selector

* fix: clarify Pollinations MCP description

* fix: complete hosted MCP rollout ordering

* fix: finalize hosted MCP proxy contracts
Co-authored-by: pollinations-ai[bot] <pollinations-ai[bot]@users.noreply.github.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@qodo-code-review

qodo-code-review Bot commented Aug 24, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Delay public community model price/visibility changes by 12 hours

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🐞 Bug fix 🕐 40+ Minutes

Grey Divider

AI Description

• Queue public price/visibility updates for 12 hours using pending fields.
• Refactor community listings to typed payloads and stronger fallback/visibility rules.
• Add tests, docs, and deployment/CI updates for the new behavior.
Diagram

graph TD
UI["Enter Frontend"] --> EnterAPI["enter: community-endpoints"] --> DB[("D1: community_endpoint")]
DB --> Presenter["enter: presenter"] --> UI
DB --> GenCatalog["gen: community-models"] --> PublicAPI["gen: public models"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Background job applies queued changes
  • ➕ Keeps read paths simple (no effective/pending evaluation at read time)
  • ➕ Allows automatic cleanup of pending fields after apply
  • ➖ Requires a scheduler/cron + operational ownership
  • ➖ Harder to guarantee exactly-once apply in distributed environments
2. Single 'effective_at' + 'next_state' blob
  • ➕ Fewer columns; simpler migrations across additional deferred fields
  • ➕ Easier to extend to other delayed changes
  • ➖ Weaker type safety and harder SQL-level introspection
  • ➖ More complex partial updates (patching parts of the blob)
3. Append-only change log (event sourcing)
  • ➕ Strong auditability and easy rollback/inspection of scheduled changes
  • ➕ Supports multiple queued changes over time
  • ➖ Significantly more implementation complexity and query cost
  • ➖ Requires careful projection logic for effective state

Recommendation: The PR’s approach (pending columns + read-time effective evaluation) is the best tradeoff here: it avoids introducing cron/scheduling infrastructure, provides deterministic behavior using timestamps, and enables both Enter and Gen to consistently compute the effective state. If extending to multiple queued changes becomes a requirement, consider moving from single pending fields to a small change-log table, but that’s unnecessary for the current 12h notice requirement.

Files changed (23) +4182 / -2052

Enhancement (10) +1270 / -1181
better-auth.tsReshape community_endpoint schema and add pending change columns +40/-81

Reshape community_endpoint schema and add pending change columns

• Replaces legacy per-field columns with a typed payload column and listing type checks. Adds pendingPayload/pendingVisibility/pendingAt to support 12h delayed public price/visibility changes, and renames disable fields to hidden fields.

shared/db/better-auth.ts

community-endpoints.tsRefactor community endpoints API and queue delayed public changes +280/-781

Refactor community endpoints API and queue delayed public changes

• Splits validation/presentation into dedicated modules, adds endpoint-agent creation, and updates create/update flows to store listing payloads. For public listings, price/visibility updates are queued into pending columns and become effective after PRICE_CHANGE_DELAY_MS.

enter.pollinations.ai/src/routes/community-endpoints.ts

presenter.tsExpose effective vs pending values for UI +101/-0

Expose effective vs pending values for UI

• Computes whether pending changes are ready (pendingAt + delay) and returns effective visibility/payload accordingly. Includes a pending object for proxies so the UI can display scheduled changes and their effectiveAt timestamp.

enter.pollinations.ai/src/routes/community-endpoints/presenter.ts

fallbacks.tsFallback resolution and concealment-safe validation +172/-0

Fallback resolution and concealment-safe validation

• Implements fallback candidate validation with consistent rules for discovery and write-time checks. Conceals private/hidden third-party models as 'missing' to avoid existence leakage; rejects agent/delegating targets for fallbacks.

enter.pollinations.ai/src/routes/community-endpoints/fallbacks.ts

community-models.tsApply post-deadline effective values when building the public catalog +112/-85

Apply post-deadline effective values when building the public catalog

• Reads pendingAt/pendingPayload/pendingVisibility and flips to pending values only after PRICE_CHANGE_DELAY_MS. Adopts the new listing type + payload parsing model and uses AGENT_RUNTIME_BASE_URL for prompt_agent resolution.

gen.pollinations.ai/src/community-models.ts

types.tsFrontend types for new listing kinds and fields +97/-31

Frontend types for new listing kinds and fields

• Splits CommunityEndpoint into proxy vs agent variants and adds fields like paidOnly, fallbacks, hidden state, and advertised metadata/capabilities. Updates form state defaults accordingly.

enter.pollinations.ai/frontend/src/components/community-endpoints/types.ts

community-endpoint-card.tsxUI tweaks for hidden vs agent listings +40/-33

UI tweaks for hidden vs agent listings

• Updates rendering logic to recognize agent listings via type, display hidden state (replacing disabled), and conditionally show pricing/modality details only for proxy listings.

enter.pollinations.ai/frontend/src/components/community-endpoints/community-endpoint-card.tsx

community-endpoint-dialog.tsxDialog adjustments for endpoint-agent vs proxy editing +239/-132

Dialog adjustments for endpoint-agent vs proxy editing

• Restricts edit support to editable listing types and skips upstream model discovery/testing paths for endpoint agents. Renames fallbackModelIds to fallbacks and updates submission requirements accordingly.

enter.pollinations.ai/frontend/src/components/community-endpoints/community-endpoint-dialog.tsx

earnings.tsAdd CLI command to view developer earnings +115/-0

Add CLI command to view developer earnings

• Introduces an 'earnings' command that calls '/account/earnings', summarizes totals, and prints a per-entity table in human output mode.

packages/polli-cli/src/commands/earnings.ts

my-models.tsUpdate CLI model payload to match new listing schema +74/-38

Update CLI model payload to match new listing schema

• Updates the CLI types and request body mapping for proxy vs agent listings, adds transcription modality support, and renames fallbackModels to fallbacks. Adds paidOnly support.

packages/polli-cli/src/commands/my-models.ts

Bug fix (2) +78 / -50
worker.jsReject MCP batch requests explicitly +18/-0

Reject MCP batch requests explicitly

• Adds a guard that returns a 400 invalid_request when the POST body is an array, preventing unsupported batch semantics from reaching the MCP handler.

apps/mcp/worker.js

stripe-webhooks.tsRound Stripe credits to billing precision and refactor analytics payload +60/-50

Round Stripe credits to billing precision and refactor analytics payload

• Rounds checkout-session credits using POLLEN_BILLING_PRECISION to avoid float drift. Extracts helper to build Tinybird event payloads and reduces duplication across webhook handlers.

enter.pollinations.ai/src/routes/stripe-webhooks.ts

Refactor (5) +932 / -727
community-endpoints.tsAdd delayed-change constant and typed listing payload model +267/-25

Add delayed-change constant and typed listing payload model

• Introduces PRICE_CHANGE_DELAY_MS and a new listing-type model (proxy/prompt_agent/endpoint_agent) with parseListingPayload for normalized reads. Adds advertised metadata normalization and fallback balance eligibility helpers.

shared/community-endpoints.ts

schemas.tsCentralize request/response schemas for community models/agents +315/-0

Centralize request/response schemas for community models/agents

• Introduces Zod schemas for create/update/test/list operations, including paidOnly, fallbacks, and advertised metadata. Updates validation messaging and modality support (including transcription).

enter.pollinations.ai/src/routes/community-endpoints/schemas.ts

proxy-policy.tsPolicy derivation for proxy listings (prices, modality, advertised) +233/-0

Policy derivation for proxy listings (prices, modality, advertised)

• Creates a single policy derivation layer that enforces input modalities, advertised restrictions, and price limits. Normalizes visibility behavior (private => free/unpriced; public => priced/paidOnly allowed).

enter.pollinations.ai/src/routes/community-endpoints/proxy-policy.ts

client.tsRefactor text generation to reuse chat helpers +38/-101

Refactor text generation to reuse chat helpers

• Replaces duplicated request construction with shared helper methods that build messages/options and delegate to chat/chatStream. Keeps option mapping explicit without SDK-owned defaults.

packages/sdk/src/client.ts

auto-top-up.tsRestructure auto top-up billing implementation +79/-601

Restructure auto top-up billing implementation

• Refactors the auto-top-up module (moving toward smaller helpers/types) and introduces POLLEN_BILLING_PRECISION usage for balance mutation consistency.

enter.pollinations.ai/src/utils/stripe-billing/auto-top-up.ts

Tests (1) +72 / -0
community-endpoint-price-delay.test.tsIntegration test for delayed public price change +72/-0

Integration test for delayed public price change

• Verifies that a pendingPayload is not applied before the deadline and becomes effective after pendingAt + PRICE_CHANGE_DELAY_MS.

enter.pollinations.ai/test/integration/community-endpoint-price-delay.test.ts

Documentation (2) +1503 / -85
APIDOCS.mdRegenerate API documentation +1392/-85

Regenerate API documentation

• Updates generated API docs to reflect new/changed endpoints and schemas (including community models/agents).

APIDOCS.md

BRING_YOUR_OWN_MODEL.mdAdd BYOM documentation +111/-0

Add BYOM documentation

• Adds documentation for bringing your own model, including setup and usage guidance.

BRING_YOUR_OWN_MODEL.md

Other (3) +327 / -9
0055_price_change_delay.sqlDB migration for pending price/visibility delay +3/-0

DB migration for pending price/visibility delay

• Adds pending_payload, pending_visibility, and pending_at columns to community_endpoint.

enter.pollinations.ai/drizzle/0055_price_change_delay.sql

deploy-cloudflare-production.ymlAdd production Cloudflare deployment workflow +322/-0

Add production Cloudflare deployment workflow

• Introduces a new production deploy workflow with expanded steps and environment handling for Cloudflare apps.

.github/workflows/deploy-cloudflare-production.yml

ci-pull-request-checks.ymlAdjust PR CI checks workflow +2/-9

Adjust PR CI checks workflow

• Updates the pull-request checks workflow configuration to reflect current CI expectations and reduce/reshape steps.

.github/workflows/ci-pull-request-checks.yml

@qodo-code-review

qodo-code-review Bot commented Aug 24, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2) 📜 Skill insights (0)

Grey Divider


Action required

1. APIDOCS.md edited in PR 📘 Rule violation ⚙ Maintainability
Description
This PR directly edits APIDOCS.md, which is prohibited for feature PRs because it must be
generated from OpenAPI sources. Manual edits will be overwritten and can desync the published API
reference from the generation pipeline.
Code

APIDOCS.md[R16-19]

+**1. Get an API key** at [enter.pollinations.ai](https://enter.pollinations.ai/keys). Use the key type for your environment:

-- `sk_*` — secret key for backend use (full account access)
-- `pk_*` — publishable key, safe to ship in browsers and mobile apps
+- `sk_*` — secret key for backend use. Never ship it in a browser, mobile app, or repository.
+- `pk_*` App Key — public OAuth client id for BYOP. Use it to obtain a scoped user `sk_*`; do not use raw publishable keys for new browser generation integrations.
Evidence
PR Compliance ID 10 forbids editing or regenerating APIDOCS.md in feature PRs; the diff shows
direct changes to APIDOCS.md content (e.g., updated key guidance and integration guide links).

AGENTS.md: Do not edit or regenerate APIDOCS.md in feature PRs; update OpenAPI sources instead
APIDOCS.md[14-30]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`APIDOCS.md` is being edited directly, but compliance requires updating the OpenAPI source files instead and letting `APIDOCS.md` be generated.

## Issue Context
This PR includes multiple content changes inside `APIDOCS.md` (generated output). The correct fix is to revert `APIDOCS.md` changes and apply documentation updates in the OpenAPI source inputs.

## Fix Focus Areas
- APIDOCS.md[14-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Nonexistent model routes advertised ✓ Resolved 🐞 Bug ≡ Correctness
Description
Community text and image metadata now advertises /v1/text, /v1/text/{prompt}, and
/v1/image/{prompt}, but the corresponding generation routes remain /text, /text/:prompt, and
/image/:prompt. Model discovery therefore tells clients to call endpoints that are not registered
and omits the working legacy paths.
Code

gen.pollinations.ai/src/community-models.ts[R25-26]

+    "/v1/text",
+    "/v1/text/{prompt}",
Evidence
The helper's new supported paths flow directly into every community generation entry, while the
route table and static text endpoint list retain the unversioned paths.

gen.pollinations.ai/src/community-models.ts[23-42]
gen.pollinations.ai/src/model-registry.ts[101-110]
gen.pollinations.ai/src/model-registry.ts[129-145]
gen.pollinations.ai/src/routes/generation-executor.ts[76-119]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Community model metadata lists versioned convenience endpoints that the worker does not implement.

## Issue Context
Supported endpoint values feed generation registry metadata and public model discovery.

## Fix Focus Areas
- gen.pollinations.ai/src/community-models.ts[23-42]
- gen.pollinations.ai/src/routes/generation-executor.ts[76-119]
- gen.pollinations.ai/src/model-registry.ts[129-145]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Missing delay constant export ⊘ Outdated 🐞 Bug ≡ Correctness
Description
Both runtime readers import PRICE_CHANGE_DELAY_MS from @shared/community-endpoints.ts, but that
module does not export it. TypeScript compilation therefore fails before the delayed-price feature
can be deployed.
Code

enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[R5-6]

+    PRICE_CHANGE_DELAY_MS,
+    parseListingPayload,
Evidence
The new presenter and registry imports reference an export absent from the complete shared module;
repository-wide searches find only the imports and comment, not a declaration.

enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[1-7]
gen.pollinations.ai/src/community-models.ts[3-8]
shared/community-endpoints.ts[19-25]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`PRICE_CHANGE_DELAY_MS` is imported but is not exported by the shared community-endpoints module, causing a compile-time module-export error.

## Issue Context
Both Enter and Gen use this value to determine when queued changes become effective.

## Fix Focus Areas
- shared/community-endpoints.ts[19-25]
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[1-7]
- gen.pollinations.ai/src/community-models.ts[3-8]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (7)
4. Price update blocks privatization ✓ Resolved 🐞 Bug ≡ Correctness
Description
A public proxy update that changes price or paidOnly while setting visibility to private writes
the payload but never writes visibility. The model consequently remains publicly visible despite
the requested private transition.
Code

enter.pollinations.ai/src/routes/community-endpoints.ts[R793-800]

+                    const priceChangedOnPublic =
+                        endpoint.visibility === "public" &&
+                        !isGoingPrivate &&
+                        (input.paidOnly !== undefined ||
+                            COMMUNITY_ENDPOINT_PRICE_FIELDS.some(
+                                ({ key }) => input[key] !== undefined,
+                            ));
+                    if (isGoingPublic || priceChangedOnPublic) {
Evidence
The payload branch clears pending state and updates payload only; the update.visibility assignment
is in the mutually exclusive final branch.

enter.pollinations.ai/src/routes/community-endpoints.ts[713-720]
enter.pollinations.ai/src/routes/community-endpoints.ts[793-820]
enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[22-46]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The proxy payload-update branch skips the only visibility assignment when a request combines a price/policy change with `visibility: private`.

## Issue Context
`priceChangedOnPublic` explicitly excludes `isGoingPrivate`, so the payload is applied immediately but `update.visibility` is never set.

## Fix Focus Areas
- enter.pollinations.ai/src/routes/community-endpoints.ts[713-720]
- enter.pollinations.ai/src/routes/community-endpoints.ts[793-813]
- enter.pollinations.ai/src/routes/community-endpoints.ts[814-820]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Expired changes get reverted ⊘ Outdated 🐞 Bug ≡ Correctness
Description
Later updates always derive proxy policy from endpoint.payload, even after an expired
pendingPayload has become the effective runtime state. A partial edit after the deadline can
therefore restore old prices, paid-only policy, fallbacks, or credentials instead of preserving the
effective values.
Code

enter.pollinations.ai/src/routes/community-endpoints.ts[R753-756]

+                const stored = parseListingPayload("proxy", endpoint.payload);
+                if (!stored) {
+                    throw new Error(`Invalid proxy payload for ${endpoint.id}`);
+                }
Evidence
The update handler parses only the old payload, while the presenter and generation registry switch
to the pending payload after 12 hours. Since queueing never copies the pending payload into
payload, the next derived policy starts from obsolete values.

enter.pollinations.ai/src/routes/community-endpoints.ts[753-760]
enter.pollinations.ai/src/routes/community-endpoints.ts[793-812]
enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[65-75]
gen.pollinations.ai/src/community-models.ts[104-115]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Updates after a pending deadline use stale persisted state and can revert the change that callers already see as effective.

## Issue Context
Readers switch to `pendingPayload` by time, but the write path never promotes it or selects it as the update baseline.

## Fix Focus Areas
- enter.pollinations.ai/src/routes/community-endpoints.ts[753-812]
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[22-33]
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[65-75]
- gen.pollinations.ai/src/community-models.ts[104-115]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Secret file changed in PR 📘 Rule violation ⛨ Security
Description
This PR modifies an encrypted secrets file (enter.pollinations.ai/secrets/staging.vars.json)
alongside unrelated feature code changes. Mixing secret rotations/updates with feature work
increases review and deployment risk and violates the isolation requirement.
Code

enter.pollinations.ai/secrets/staging.vars.json[R19-21]

+	"DISCORD_CLIENT_ID": "ENC[AES256_GCM,data:uDis8Q44wsMTgkPDmJPX4firRg==,iv:SlB/nm8nFoEM61zsTscMStXE7+scpQKr+eyPB9qWZ30=,tag:+tZJh4eKrYzui9i+WgVtyw==,type:str]",
+	"DISCORD_CLIENT_SECRET": "ENC[AES256_GCM,data:6EjgHFCk08X6aL4U39p1FkOLHi1j+vV/BQryDuDX+Hc=,iv:usjPOmKQDUkTckkgQ6Jz7xuNq7xdAI6r3LbYWbNuGg4=,tag:zBCxkEUU4+wSCVkRUFyxrA==,type:str]",
+	"DISCORD_BOT_TOKEN": "ENC[AES256_GCM,data:Mlu0IMvjvvpqNiirxuWwPHRf3S4Vt32c/Ocdr+YRvmlirlSIlrZISqW4PnpqxYvwfKGjDbW3DzayTs0UeCwiVOqT715J+w==,iv:eP5HFG+0zNjaOhSP58vUENgMD1QYvwGb1SmZOilXOyM=,tag:3dEIYyLOorL9DCExmZq1gw==,type:str]",
Evidence
PR Compliance ID 6 requires encrypted secret-file changes to be isolated to a dedicated PR; this PR
updates the SOPS-encrypted staging vars file and also includes unrelated feature code changes (e.g.,
new pending fields for community endpoints).

AGENTS.md: Encrypted secret-file changes must be isolated to a dedicated PR and must not be bundled with feature/pricing/refactor changes
enter.pollinations.ai/secrets/staging.vars.json[19-43]
shared/db/better-auth.ts[226-234]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An encrypted secret file is modified in the same PR as non-secret feature changes, which is not allowed.

## Issue Context
`enter.pollinations.ai/secrets/staging.vars.json` adds new encrypted Discord credentials, while the PR also changes application code (e.g., community endpoint DB schema).

## Fix Focus Areas
- enter.pollinations.ai/secrets/staging.vars.json[19-43]
- shared/db/better-auth.ts[226-234]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Delay migration is unregistered 🐞 Bug ☼ Reliability
Description
Migration 0055_price_change_delay.sql exists but is not recorded in Drizzle’s migration
journal/metadata, so journal-driven deployments can skip applying the new pending-delay columns.
This also risks future drizzle-kit generate runs reusing or conflicting with index 0055 because
generation relies on the journal/snapshots that currently stop at 0054, while the application schema
and write path already expect those columns during community endpoint updates.
Code

enter.pollinations.ai/drizzle/0055_price_change_delay.sql[R1-3]

+ALTER TABLE `community_endpoint` ADD `pending_payload` text;--> statement-breakpoint
+ALTER TABLE `community_endpoint` ADD `pending_visibility` text;--> statement-breakpoint
+ALTER TABLE `community_endpoint` ADD `pending_at` integer;--> statement-breakpoint
Evidence
The provided evidence indicates that the SQL migration file adds the new columns and the production
schema/write path already uses them, yet the Drizzle metadata does not reflect this change: the
_journal.json ends at migration/tag 0054 and there is no corresponding 0055 snapshot in the
metadata directory. Because the repo’s migration-generation workflow uses Drizzle Kit (via
drizzle-kit generate), which relies on the journal/snapshot metadata to determine the next
migration index and baseline, the missing 0055 entry can cause deployments to omit the migration and
can also lead to subsequent generated migrations reusing 0055 or being generated from a state that
lacks the pending columns, creating conflicts with the hand-written file.

enter.pollinations.ai/drizzle/0055_price_change_delay.sql[1-3]
enter.pollinations.ai/drizzle/meta/_journal.json[369-391]
shared/db/better-auth.ts[226-234]
enter.pollinations.ai/src/routes/community-endpoints.ts[800-812]
enter.pollinations.ai/drizzle/meta/_journal.json[383-391]
enter.pollinations.ai/package.json[22-23]
shared/db/better-auth.ts[227-234]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The hand-written migration `0055_price_change_delay.sql` that adds pending-delay columns is not represented in Drizzle’s migration journal (and appears to lack corresponding snapshot metadata), which can cause normal journal-driven deployments to skip applying the columns. This mismatch also puts future `drizzle-kit generate` runs at risk of reusing migration index 0055 or generating from an outdated baseline (ending at 0054/0053), leading to conflicting or incorrect subsequent schema migrations while the application schema/routes already assume the columns exist.

## Issue Context
- A new SQL migration file `0055_price_change_delay.sql` was added to introduce pending-delay columns.
- Drizzle’s `_journal.json` currently ends at 0054, and the metadata directory has no 0055 snapshot.
- The repository uses `drizzle-kit generate` for future migrations, which depends on Drizzle’s journal/snapshot metadata.
- The schema and route/write path now require all three columns immediately during community endpoint updates, so missing columns in deployed DBs will break reads/writes.

## Fix Focus Areas
- enter.pollinations.ai/drizzle/0055_price_change_delay.sql[1-3]
- enter.pollinations.ai/drizzle/meta/_journal.json[369-391]
- shared/db/better-auth.ts[226-234]
- enter.pollinations.ai/package.json[22-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Endpoint and credential diverge ✓ Resolved 🐞 Bug ☼ Reliability
Description
For a public model update that changes the base URL, bearer token, and a price, the base URL is
applied immediately while the new credential is stored only in the 12-hour pending payload. Requests
are sent to the new endpoint with the old credential until the deadline, causing authentication
failures.
Code

enter.pollinations.ai/src/routes/community-endpoints.ts[R773-774]

+                if (input.baseUrl !== undefined) {
+                    update.baseUrl = normalizeInputBaseUrl(input.baseUrl);
Evidence
The update schema accepts base URL, bearer token, and prices together. The handler writes the URL
directly, embeds the new token in the candidate payload, and queues that entire payload whenever any
price field is present on a public model.

enter.pollinations.ai/src/routes/community-endpoints/schemas.ts[156-177]
enter.pollinations.ai/src/routes/community-endpoints.ts[773-810]
enter.pollinations.ai/src/routes/community-endpoints/proxy-policy.ts[221-232]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Combined endpoint, credential, and price updates split an operationally atomic configuration across immediate and delayed state.

## Issue Context
Only price and visibility should be delayed; routing target and its matching credential must become active together.

## Fix Focus Areas
- enter.pollinations.ai/src/routes/community-endpoints.ts[773-810]
- enter.pollinations.ai/src/routes/community-endpoints/schemas.ts[156-177]
- enter.pollinations.ai/src/routes/community-endpoints/proxy-policy.ts[221-232]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Pending responses fail validation ⊘ Outdated 🐞 Bug ≡ Correctness
Description
toCommunityEndpointResponse adds pending to proxy responses, but the strict proxy response
schema does not define that property, so listing or updating a model with a queued price payload
throws a Zod error after the database update has already succeeded. Clients therefore receive a
failure for a persisted change and cannot display the schedule.
Code

enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[99]

+        pending,
Evidence
The presenter constructs a non-null pending object and passes it into a strict discriminated
response schema; the proxy arm lists all accepted fields but has no pending field.

enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[72-100]
enter.pollinations.ai/src/routes/community-endpoints/schemas.ts[233-264]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Proxy responses containing a queued change fail strict Zod validation because `pending` is not declared in the response schema.

## Issue Context
The presenter constructs `pending` and then parses the result through `CommunityEndpointResponseSchema`.

## Fix Focus Areas
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[72-100]
- enter.pollinations.ai/src/routes/community-endpoints/schemas.ts[233-246]
- enter.pollinations.ai/frontend/src/components/community-endpoints/types.ts[70-82]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Stale publish queue survives reversal ⊘ Outdated 🐞 Bug ≡ Correctness
Description
Reverting a queued private-to-public transition back to private does not clear its pending fields
because transition detection relies on the persisted visibility still being private. After the
original deadline passes, the stale pendingVisibility/pendingAt is treated as effective and the
model becomes public despite the owner's cancellation.
Code

enter.pollinations.ai/src/routes/community-endpoints.ts[R818-820]

+                } else {
+                    update.visibility = resolvedVisibility;
+                }
Evidence
The publish path queues a future public change by setting pendingVisibility = public (and
pendingAt) while leaving the persisted visibility as private, but the later “cancel” update
falls into a branch that only writes the current visibility and does not clear the pending fields
because isGoingPrivate/transition detection is based on the persisted visibility column.
Subsequent readers (the presenter and other visibility computation) prefer the matured pending state
over the stored visibility once the deadline has passed, so the retained pending values remain
authoritative and make the model public anyway.

enter.pollinations.ai/src/routes/community-endpoints.ts[814-820]
enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[22-26]
gen.pollinations.ai/src/community-models.ts[104-115]
enter.pollinations.ai/src/routes/community-endpoints.ts[713-720]
enter.pollinations.ai/src/routes/community-endpoints.ts[741-749]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A visibility update intended to cancel a queued publish (private → public) leaves `pendingVisibility` and `pendingAt` intact because the cancellation path only writes the current `visibility` and transition detection relies on the persisted visibility still being `private`. As a result, once the original deadline passes, readers that treat matured pending visibility as effective will publish the model anyway.

## Issue Context
When a publish is scheduled, the system stores the future state in `pendingVisibility = public` (and `pendingAt`) while keeping `visibility` as `private`. A subsequent request to set visibility to `private` does not satisfy `isGoingPrivate` / the transition logic (since persisted visibility is not `public`), so it does not clear the pending fields; later, effective visibility computation (including the presenter and other readers) prefers matured pending state, causing the old schedule to remain in effect even after the owner “cancels.”

## Fix Focus Areas
- enter.pollinations.ai/src/routes/community-endpoints.ts[713-720]
- enter.pollinations.ai/src/routes/community-endpoints.ts[814-820]
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[22-33]
- gen.pollinations.ai/src/community-models.ts[104-115]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

11. CLI defaults to paid-only 🐞 Bug ≡ Correctness
Description
Commander assigns true by default for the negated --no-paid-only option, and modelBody
forwards that value whenever users omit both flags. Creating or updating a model therefore
unintentionally sets paidOnly: true, contrary to the documented default.
Code

packages/polli-cli/src/commands/my-models.ts[R258-261]

+            "--paid-only",
+            "Only accept Paid Pollen, for a pay-as-you-go upstream whose cost free Quest Pollen would not cover",
+        )
+        .option("--no-paid-only", "Accept Quest or Paid Pollen (default)")
Evidence
The new negated option has no explicit default and is forwarded by the common request-body builder;
identical options exist for update.

packages/polli-cli/src/commands/my-models.ts[106-119]
packages/polli-cli/src/commands/my-models.ts[258-261]
packages/polli-cli/src/commands/my-models.ts[311-314]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The paired positive and negated Commander options cause omitted `--paid-only` input to be forwarded as `paidOnly: true`.

## Issue Context
This affects both create and update because `modelBody` copies any defined `paidOnly` option into API requests.

## Fix Focus Areas
- packages/polli-cli/src/commands/my-models.ts[106-119]
- packages/polli-cli/src/commands/my-models.ts[258-261]
- packages/polli-cli/src/commands/my-models.ts[311-314]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Visibility schedule stays hidden ⊘ Outdated 🐞 Bug ≡ Correctness
Description
The presenter only creates a pending response when pendingPayload exists, so a visibility-only
private-to-public transition has no schedule in the API response. Endpoint-agent publication has the
same problem, preventing the UI or clients from showing the promised effective time.
Code

enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[R73-74]

+    if (!ready && row.pendingAt && row.pendingPayload) {
+        const pendingPayload = parseListingPayload("proxy", row.pendingPayload);
Evidence
The visibility-only update branch writes pendingVisibility and pendingAt but not
pendingPayload; the presenter's pending block requires all three, and endpoint-agent responses
return before this block entirely.

enter.pollinations.ai/src/routes/community-endpoints.ts[814-817]
enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[53-87]
enter.pollinations.ai/src/routes/community-endpoints/schemas.ts[247-264]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Visibility-only publication schedules are stored but omitted from API responses.

## Issue Context
A publication may have `pendingVisibility` and `pendingAt` without any pending payload, for both proxy and endpoint-agent listings.

## Fix Focus Areas
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[22-33]
- enter.pollinations.ai/src/routes/community-endpoints/presenter.ts[53-87]
- enter.pollinations.ai/src/routes/community-endpoints/schemas.ts[233-264]
- enter.pollinations.ai/src/routes/community-endpoints.ts[814-817]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: 🧠 Deep: This is an exceptionally dense cross-cutting PR with 278 files and 1,281 hunks spanning billing, database migrations, public API behavior, generation paths, frontend, and deployment, making multiple independent subtle defects plausibly easy to miss.

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread APIDOCS.md
Comment on lines +16 to +19
**1. Get an API key** at [enter.pollinations.ai](https://enter.pollinations.ai/keys). Use the key type for your environment:

- `sk_*` — secret key for backend use (full account access)
- `pk_*` — publishable key, safe to ship in browsers and mobile apps
- `sk_*` — secret key for backend use. Never ship it in a browser, mobile app, or repository.
- `pk_*` App Key — public OAuth client id for BYOP. Use it to obtain a scoped user `sk_*`; do not use raw publishable keys for new browser generation integrations.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. apidocs.md edited in pr 📘 Rule violation ⚙ Maintainability

This PR directly edits APIDOCS.md, which is prohibited for feature PRs because it must be
generated from OpenAPI sources. Manual edits will be overwritten and can desync the published API
reference from the generation pipeline.
Agent Prompt
## Issue description
`APIDOCS.md` is being edited directly, but compliance requires updating the OpenAPI source files instead and letting `APIDOCS.md` be generated.

## Issue Context
This PR includes multiple content changes inside `APIDOCS.md` (generated output). The correct fix is to revert `APIDOCS.md` changes and apply documentation updates in the OpenAPI source inputs.

## Fix Focus Areas
- APIDOCS.md[14-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +19 to +21
"DISCORD_CLIENT_ID": "ENC[AES256_GCM,data:uDis8Q44wsMTgkPDmJPX4firRg==,iv:SlB/nm8nFoEM61zsTscMStXE7+scpQKr+eyPB9qWZ30=,tag:+tZJh4eKrYzui9i+WgVtyw==,type:str]",
"DISCORD_CLIENT_SECRET": "ENC[AES256_GCM,data:6EjgHFCk08X6aL4U39p1FkOLHi1j+vV/BQryDuDX+Hc=,iv:usjPOmKQDUkTckkgQ6Jz7xuNq7xdAI6r3LbYWbNuGg4=,tag:zBCxkEUU4+wSCVkRUFyxrA==,type:str]",
"DISCORD_BOT_TOKEN": "ENC[AES256_GCM,data:Mlu0IMvjvvpqNiirxuWwPHRf3S4Vt32c/Ocdr+YRvmlirlSIlrZISqW4PnpqxYvwfKGjDbW3DzayTs0UeCwiVOqT715J+w==,iv:eP5HFG+0zNjaOhSP58vUENgMD1QYvwGb1SmZOilXOyM=,tag:3dEIYyLOorL9DCExmZq1gw==,type:str]",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Secret file changed in pr 📘 Rule violation ⛨ Security

This PR modifies an encrypted secrets file (enter.pollinations.ai/secrets/staging.vars.json)
alongside unrelated feature code changes. Mixing secret rotations/updates with feature work
increases review and deployment risk and violates the isolation requirement.
Agent Prompt
## Issue description
An encrypted secret file is modified in the same PR as non-secret feature changes, which is not allowed.

## Issue Context
`enter.pollinations.ai/secrets/staging.vars.json` adds new encrypted Discord credentials, while the PR also changes application code (e.g., community endpoint DB schema).

## Fix Focus Areas
- enter.pollinations.ai/secrets/staging.vars.json[19-43]
- shared/db/better-auth.ts[226-234]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread enter.pollinations.ai/src/routes/community-endpoints/presenter.ts Outdated
Comment thread enter.pollinations.ai/src/routes/community-endpoints.ts
Comment thread enter.pollinations.ai/src/routes/community-endpoints.ts
Comment thread enter.pollinations.ai/src/routes/community-endpoints/presenter.ts Outdated
Comment thread gen.pollinations.ai/src/community-models.ts Outdated
Comment thread enter.pollinations.ai/src/routes/community-endpoints/presenter.ts Outdated
Comment thread enter.pollinations.ai/src/routes/community-endpoints.ts Outdated
Comment thread enter.pollinations.ai/src/routes/community-endpoints.ts Outdated
Comment on lines +258 to +261
"--paid-only",
"Only accept Paid Pollen, for a pay-as-you-go upstream whose cost free Quest Pollen would not cover",
)
.option("--no-paid-only", "Accept Quest or Paid Pollen (default)")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

12. Cli defaults to paid-only 🐞 Bug ≡ Correctness

Commander assigns true by default for the negated --no-paid-only option, and modelBody
forwards that value whenever users omit both flags. Creating or updating a model therefore
unintentionally sets paidOnly: true, contrary to the documented default.
Agent Prompt
## Issue description
The paired positive and negated Commander options cause omitted `--paid-only` input to be forwarded as `paidOnly: true`.

## Issue Context
This affects both create and update because `modelBody` copies any defined `paidOnly` option into API requests.

## Fix Focus Areas
- packages/polli-cli/src/commands/my-models.ts[106-119]
- packages/polli-cli/src/commands/my-models.ts[258-261]
- packages/polli-cli/src/commands/my-models.ts[311-314]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.