Changelog
2026-05-01¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | modified | app/providers/bedrock/chat_modules/streaming_async.py | Phase 4B Bedrock async migration — replaced per-event asyncio.to_thread(next, ...) bridge with producer-thread + asyncio.Queue. Consumer side is now pure await queue.get(); only one fire-and-forget to_thread remains for the spawn. ruff clean, 9 existing streaming_async tests + 23 chat_modules tests + 17 bedrock/contract tests all pass. |
manual (SSE plan Phase 4B) |
| — | created | app/streaming/dispatchers.py | Phase 7B per-provider async streaming registry — dispatch_stream(provider_id, …) and is_supported(provider_id). Maps each of the 9 providers to its streaming_async module + correct client attribute (async_client/client/genai) + signature quirks (anthropic's original_model_name). |
manual (SSE plan Phase 7B) |
| — | modified | app/api/routers/chat_modules/stream_pipeline.py | Replaced hardcoded _dispatch_openai_stream with the new registry-based dispatch_stream(provider_id, …); docstring updated to reflect 9-provider coverage. |
manual (SSE plan Phase 7B) |
| — | modified | app/api/routers/chat_modules/stream_handler.py | Widened the flag dispatch from provider_id == "openai" to is_async_streaming_supported(provider_id); extracted legacy _generate_stream to a sibling module to clear the 200-line hard cap. |
manual (SSE plan Phase 7B) |
| — | created | app/api/routers/chat_modules/stream_legacy.py | Holds the legacy sync _generate_stream and helpers split out of stream_handler.py. Re-exported from stream_handler so existing patches (stream_handler._generate_stream) keep working. Slated for deletion once Phase 7B widening covers every provider in production. |
manual (SSE plan Phase 7B) |
| — | modified | tests/api/routers/chat_modules/test_stream_pipeline_async.py | Updated patch target (_dispatch_openai_stream → dispatch_stream with provider_id arg), renamed test_flag_on_non_openai_keeps_sync_path → test_flag_on_unknown_provider_keeps_sync_path (anthropic is now supported), added test_flag_on_routes_anthropic_to_async. 5 tests pass. |
manual (SSE plan Phase 7B) |
| — | modified | tests/api/routers/chat_modules/test_stream_handler_baseline.py | Repointed Chat/stream_manager/finalize_stream_billing patches from stream_handler to stream_legacy (where the legacy sync code now lives). 7 baseline tests pass. |
manual (SSE plan Phase 7B) |
| — | created | nginx/conf.d/prod/api_streaming.conf | Phase 8 SSE nginx config — dedicated location = blocks for /v1/chat/completions and /api/v1/chat/completions with proxy_buffering off, proxy_cache off, chunked_transfer_encoding on, proxy_read_timeout 600s, proxy_send_timeout 600s, Connection "" + HTTP/1.1 keep-alive. Mirrors the CORS/proxy plumbing from api.conf. |
manual (SSE plan Phase 8) |
| — | modified | nginx/conf.d/prod.conf | Added include /etc/nginx/conf.d/prod/api_streaming.conf; BEFORE the api.conf include so the streaming exact-match locations are seen first (cosmetic — location = wins regardless of file order). |
manual (SSE plan Phase 8) |
| — | created | tests/load/locustfile_sse.py | Phase 9 50-stream Locust scenario — POSTs to /v1/chat/completions with stream=true, records TTFC, total stream duration, max inter-chunk gap, fails on missing [DONE] or coalesced single-chunk responses. Env-driven (SSE_LOAD_API_KEY required, model/prompt/path/max_tokens optional). |
manual (SSE plan Phase 9) |
| — | created | docs/baseline/2026-04-19-post-sse.md | Phase 9 post-baseline TEMPLATE — gate criteria checklist, peaks comparison table vs pre-SSE, per-worker event-loop block-time table (≥80% drop required), per-provider to_thread audit table, nginx + error verification sections, sign-off block. Numbers filled at deploy time. |
manual (SSE plan Phase 9) |
2026-05-02¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | modified | docs/usage/streaming.md | Replaced legacy "SSE Format" section (described the old data: {"content":"…"} shape) with the actual Phase 7B wire format: named event: usage_start / event: usage_final events, the {type, provider, choices} envelope, and a 9-provider table. Pointed at the new SSE Events page for the per-event schema. 195 lines. |
manual (mkdocs update for Phase 7B canary) |
| — | created | docs/usage/sse-events.md | New comprehensive reference for every SSE event the streaming pipeline emits (usage_start, content, finish, usage_final, response.done, [DONE], error) plus reserved future events (rate_limit_warning, cache_hit, provider_fallback). Includes a complete Python parser example that captures cost_usd / latency_ms per stream. 167 lines. |
manual (mkdocs update for Phase 7B canary) |
| — | modified | docs/usage/tracking.md | Added "In-stream usage events" section explaining the usage_final SSE event mirrors the per-request usage object so streaming clients don't need a follow-up API call for billing. |
manual (mkdocs update for Phase 7B canary) |
| — | modified | mkdocs.yml | Added SSE Events: usage/sse-events.md to the Usage nav between Streaming and BYOK. |
manual (mkdocs update for Phase 7B canary) |
| — | modified | docs/main_plan/indoxhub_3month_plan.md | Refreshed Current State to May 2 (Week 4); marked Phase 0 complete; marked 3.5 (rate limiting) ✅ done; marked 3.15 (web playground) ✅ done; marked 3.13 (Python SDK) 🟠 partial — missing 429 retry; added "NEXT TASK" callout recommending 3.16 free tier signup credits. | manual (plan reconciliation) |
| — | deleted | todo/indoxhub_3month_plan.md | Removed duplicate copy of 3-month plan (drifted from canonical docs/main_plan/ version, dated 2026-04-06 with messy task table). docs/main_plan/ is now sole source of truth. | manual (plan reconciliation) |
| — | created | app/db/migrations/015_add_stripe_customer_and_email_verified.sql | Plan task 3.16 foundation — adds stripe_customer_id (UNIQUE) for SetupIntent flow + email_verified BOOLEAN + email_verified_at TIMESTAMP for the card-required signup credit gate (Bright Data / OpenAI / Anthropic pattern). |
manual (3.16 free signup credit) |
| — | modified | app/core/config_fields.py | Added SIGNUP_CREDIT_ENABLED (bool, default True) and SIGNUP_CREDIT_AMOUNT_USD (float, default 1.0) settings — controls the post-card-verification signup credit grant. |
manual (3.16 free signup credit) |
| — | created | app/db/billing_modules/grant_signup_credit.py | Idempotent signup credit grant function — gates on email_verified, dedupes on (user_id) AND (setup_intent_id), wraps existing add_user_credits with payment_method="signup_credit" to bypass the $10 credit_card minimum. 76 lines. |
manual (3.16 free signup credit) |
| — | modified | app/models/schema_modules/billing_schemas.py | Added SignupCreditSetupIntentResponse (returns Stripe client_secret + setup_intent_id + customer_id + publishable_key) and SignupCreditStatusResponse (eligibility + reason for the frontend "claim $1 credit" CTA). |
manual (3.16 free signup credit) |
| — | modified | app/models/schema_modules/init.py | Re-exported the two new SignupCredit schemas in import block + all list. | manual (3.16 free signup credit) |
| — | created | app/services/checkout_modules/setup_intent.py | Stripe SetupIntent flow — get_or_create_stripe_customer (persists users.stripe_customer_id) + create_signup_credit_setup_intent (off_session card capture, $0 charge, metadata {purpose: signup_credit, user_id}). 78 lines. |
manual (3.16 free signup credit) |
| — | modified | app/services/stripe_checkout_service.py | Registered create_signup_credit_setup_intent and get_or_create_stripe_customer as staticmethods on StripeCheckoutService. |
manual (3.16 free signup credit) |
| — | created | app/api/routers/stripe_checkout_modules/signup_credit.py | New endpoints: POST /signup-credit/setup-intent (creates SetupIntent, returns client_secret + publishable_key) and GET /signup-credit/status (returns eligibility + reason). Both gate on email_verified and dedupe on prior signup credit grants. 105 lines. |
manual (3.16 free signup credit) |
| — | modified | app/api/routers/stripe_checkout.py | Wired the new signup_credit_router into stripe_checkout router. |
manual (3.16 free signup credit) |
| — | modified | app/api/routers/webhook_modules/handlers.py | Added setup_intent.succeeded event branch + handle_setup_intent_succeeded handler — checks metadata.purpose == 'signup_credit' then calls grant_signup_credit(user_id, setup_intent_id, SIGNUP_CREDIT_AMOUNT_USD). Idempotent at the grant layer. |
manual (3.16 free signup credit) |
| — | modified | app/api/routers/auth_password_modules/confirmation.py | After successful activate_user(user_id) in /confirm, also call new helper _mark_email_verified(user_id) which UPDATEs users.email_verified=TRUE, email_verified_at=NOW(). This unlocks the signup credit gate. |
manual (3.16 free signup credit) |
| — | modified | app/core/config_fields.py | Added STRIPE_PUBLISHABLE_KEY setting (returned by setup-intent endpoint so frontend can init Stripe.js). |
manual (3.16 free signup credit) |
| — | created | docs/usage/signup-credit.md | Public docs page for the signup-credit flow — eligibility gates, both endpoints with request/response examples, end-to-end sequence, env-var table, OAuth note, migration notes. | manual (mkdocs update for 3.16) |
| — | modified | mkdocs.yml | Added Signup Credit: usage/signup-credit.md to the Usage Guide nav under "Pricing & Credits". |
manual (mkdocs update for 3.16) |
| — | modified | app/data/announcements.json | New 2026-05-02-signup-credit-card-verified entry (is_published=false until prod CTA flips on). Explains the why-card-verified rationale, endpoints, e2e flow, OAuth gap, and prod operational checklist. |
manual (3.16 free signup credit) |
| — | modified | docs/usage/streaming.md, docs/usage/sse-events.md | Added Material icons in frontmatter — material/play-network for Streaming, material/broadcast for SSE Events. Mirrors the curated icon pattern Models established (material/brain). 3 of 13 usage pages now icon-bearing — selective, not cluttered. |
manual (visual polish) |
| — | modified | docs/usage/{basic-usage,byok,chat,completions,embeddings,images,pricing,rate-limits,responses,stt,tracking,tts,video,vision}.md | Extended icon coverage to all 17 usage pages — every page now has a Material Design icon in its frontmatter (rocket-launch, key-variant, chat-processing, text-box-outline, vector-square, image-multiple, currency-usd, speedometer, code-json, microphone, chart-line, account-voice, video-outline, eye). Verified locally via mkdocs serve. |
manual (visual polish — full nav coverage) |
| — | modified | mkdocs.yml | Removed public GitHub references: repo_url + repo_name + theme.icon.repo (no top-right GitHub link/icon on docs site). Removed Interactive API Docs nav entry that pointed at the Swagger UI. Replaced the git-revision-date-localized plugin with hooks/build_date.py so the displayed "Documentation last built" date refreshes automatically on every build (was showing per-file last-modified, e.g. stale 04-17-2026 on the home page). |
manual (privacy + auto-versioning) |
| — | created | hooks/build_date.py | mkdocs hook — on_config sets config.extra.build_date = today_utc so the footer can render "Documentation last built on Month DD, YYYY" without any per-file or manual touch. |
manual (privacy + auto-versioning) |
| — | modified | docs/overrides/main.html | Added a {% block footer %} override that prints {{ config.extra.build_date }} in a small centered line below the existing footer. |
manual (privacy + auto-versioning) |
| — | modified | docs/README.md, docs/contributing.md, docs/api-reference/api-reference.md | Removed the three remaining links to https://api.indoxhub.com/api/v1/docs and …/api/v1/redoc so the Swagger / ReDoc surfaces are no longer linked from public docs. |
manual (privacy) |
| — | modified | app/data/announcements.json | Added a new "What's new" entry dated 2026-05-02 covering everything since the 2026-04-27 announcement: Bedrock added (9/9 providers), Phase 7B canary live in production, Phase 8 nginx tuning, Phase 9 Locust load scenario, public docs rewrite, and indoxhub v0.2.2 published to PyPI. The previous Apr 27 entry stays as the historical record. |
manual (announcements feed) |
| — | deleted | docs/plans/2026-04-19-sse-streaming.md, docs/baseline/2026-04-19-pre-sse.md, docs/baseline/2026-04-19-post-sse.md, docs/tech-debt/2026-04-19-sync-generator-sse.md | SSE plan + baseline + tech-debt scaffolding removed at project close-out per the durable rule "delete task md files when phases complete". The 3 baseline/tech-debt files were also leaking onto the public docs site. Empty plans/, baseline/, tech-debt/ dirs also removed. |
manual (close-out cleanup) |
| — | modified | mkdocs.yml | Removed plans/ from exclude_docs since the directory no longer exists. |
manual (close-out cleanup) |
| — | modified | tests/api/routers/chat_modules/conftest.py | Added enable_async_flag and patch_pipeline factory fixtures so tests no longer carry duplicated monkeypatch boilerplate. 116 lines. |
manual (200-line cap fix) |
| — | modified | tests/api/routers/chat_modules/test_stream_pipeline_async.py | Trimmed 207→175 lines by consuming the new shared fixtures from conftest. Added _record_dispatch helper to dedupe sync/async marker installation across two tests. No coverage change — same 5 cases. |
manual (200-line cap fix) |
| — | modified | .github/workflows/PROD_setup.yml | Wired two SSE-plan env vars into the .env.prod heredoc. INFLIGHT_TTL_SECONDS=60 (Phase 6 default) added to the Redis Cache section. New "SSE Streaming Pipeline Flag" section sources SSE_ASYNC_STREAMING_ENABLED from the GitHub repository Variables tab so flipping the canary on/off is a zero-code-change UI toggle followed by re-running PROD_setup → PROD_build_docker. |
manual (CI plumbing for canary activation) |
2026-04-29¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | created | app/providers/bedrock/chat_modules/init.py | New package re-exporting stream_chat_completion for Phase 4 Bedrock async streaming |
manual (SSE plan Phase 4) |
| — | created | app/providers/bedrock/chat_modules/streaming_async.py | Phase 4 Bedrock async streaming wrapper — bridges sync boto3.converse_stream() via asyncio.to_thread, yields SSEEvent for content/finish/usage/error events. Live-validated on us.amazon.nova-micro-v1:0 (us-east-2). |
manual (SSE plan Phase 4) |
| — | created | tests/providers/bedrock/init.py | Test package marker | manual |
| — | created | tests/providers/bedrock/test_streaming_async.py | 9 unit tests for Bedrock streaming wrapper: content delta, empty-text skip, message stop, metadata→usage, full event sequence, metadata-without-usage skip, error event no-raise, kwargs stripping, SSEEvent type instance | manual (SSE plan Phase 4) |
| — | modified | docs/plans/2026-04-19-sse-streaming.md | Progress section updated: Phase 4 now DONE for 9 providers (was 8). Bedrock row added to providers table ($2.73e-06 / 857 ms). Bedrock-deferred section replaced with done-state notes. Next-best step pivoted to Phase 7. | manual (SSE plan Phase 4) |
| — | created | app/providers/json/bedrock.json | Pricing registry for Bedrock-served models. One entry only: us.amazon.nova-micro-v1:0 with rates pinned to live-validated values (prompt $0.035/MTok, completion $0.14/MTok). Aliases for short forms amazon.nova-micro-v1:0 and nova-micro. Other Bedrock models tracked in follow-up issue. |
manual (SSE plan Phase 4 close-out) |
| — | modified | app/utils/model_info_modules/loader.py | Register bedrock -> bedrock.json in _PROVIDER_MAP so JSON-fallback path can resolve Bedrock alias/pricing data. |
manual (SSE plan Phase 4 close-out) |
| — | modified | app/utils/model_info_modules/_state.py | Add bedrock to _ALL_PROVIDERS so capability iteration covers it. |
manual (SSE plan Phase 4 close-out) |
| — | modified | app/utils/model_info_mongo_modules/loaders.py | Register bedrock -> bedrock.json in mongo-side PROVIDER_MAP. Make load_provider_models_from_mongo fall back to JSON when MongoDB returns zero models for a provider that has a registered JSON file (otherwise mongo-first masks JSON-only providers like Bedrock). |
manual (SSE plan Phase 4 close-out) |
| — | created | tests/providers/bedrock/test_pricing.py | 8 regression tests guarding cost lookup: provider loads ≥1 model, all 3 alias forms resolve to canonical, all 3 forms compute the live-validated rate, unknown Bedrock models fall back to 0.0 (documented contract). | manual (SSE plan Phase 4 close-out) |
| — | created | app/streaming/redis_tracking_modules/init.py | Phase 6 package re-exporting increment/decrement/list_active/get_redis_client/inflight_hash_key. |
manual (SSE plan Phase 6) |
| — | created | app/streaming/redis_tracking_modules/counter.py | Async per-user in-flight stream counter backed by Redis hash indoxhub:inflight:{user_id} with field-level TTL via Redis 7.4 HEXPIRE (key-level EXPIRE fallback for older Redis). All ops swallow Redis errors so SSE generators never break on tracking failures. ~150 lines. |
manual (SSE plan Phase 6) |
| — | created | tests/streaming/test_redis_tracking.py | 13 unit tests using unittest.mock.AsyncMock (fakeredis not installed): hash-key format, hset+hexpire path, EXPIRE fallback when HEXPIRE raises, None-user-id skip, error swallow, decrement, list_active w/ bytes-key decoding + malformed-value skip + redis-error empty fallback. |
manual (SSE plan Phase 6) |
| — | modified | app/core/config_fields.py | Added INFLIGHT_TTL_SECONDS: int = Field(default=60, env="INFLIGHT_TTL_SECONDS") for Phase 6. |
manual (SSE plan Phase 6) |
| — | modified | docs/plans/2026-04-19-sse-streaming.md | Phase 6 status flipped to DONE in Progress table. | manual (SSE plan Phase 6) |
| — | created | app/api/routers/chat_modules/stream_response_headers.py | Phase 7 — small SSE response-headers helper centralizing SSE_HEADERS + X-Request-ID. 18 lines. |
manual (SSE plan Phase 7) |
| — | created | app/api/routers/chat_modules/stream_pipeline.py | Phase 7 (Path 3) — async pipeline composer. Wraps Phase 4 OpenAI provider stream with Phase 5 inject_usage and Phase 6 redis_tracking try/finally. Flag-gated, OpenAI-only canary; other providers stay on the proven sync path. 172 lines. |
manual (SSE plan Phase 7) |
| — | modified | app/api/routers/chat_modules/stream_handler.py | Phase 7 dispatch — when SSE_ASYNC_STREAMING_ENABLED=True and provider_id=="openai", route to run_async_stream_pipeline; else existing _generate_stream unchanged. Switched headers helper. 189 lines (under 200 cap). |
manual (SSE plan Phase 7) |
| — | modified | app/core/config_fields.py | Added SSE_ASYNC_STREAMING_ENABLED: bool = Field(default=False, env="SSE_ASYNC_STREAMING_ENABLED") flag for Phase 7. |
manual (SSE plan Phase 7) |
| — | created | tests/api/routers/chat_modules/test_stream_pipeline_async.py | 4 e2e tests: flag off keeps sync path, flag on routes openai to async w/ X-Request-ID + usage_start/usage_final/response.done/[DONE], flag on non-openai keeps sync path, async pipeline decrements redis on upstream error. | manual (SSE plan Phase 7) |
| — | modified | tests/providers/bedrock/test_pricing.py | Hardened _fresh_caches autouse fixture to drop app.db + model_info_mongo_modules from sys.modules before clearing caches, so test ordering with tests/api/routers/chat_modules/ (which installs app.resources stubs) cannot leave app.db half-loaded for the bedrock pricing test. |
manual (SSE plan Phase 7 — test isolation) |
| — | modified | docs/plans/2026-04-19-sse-streaming.md | Phase 7 status flipped to DONE (Path 3 canary). Notes 7B widening to other providers as follow-up. | manual (SSE plan Phase 7) |
2026-04-24¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | modified | app/data/announcements.json | Added 3 announcements (model-arena-launch, image-playground-redesign, audio-playground-redesign) for 2026-04-24 | manual |
| — | modified | app/utils/stream_manager.py | Added per-stream threading.Event cancel signals (#170) — get_cancel_event, set on cancel/timeout, cleanup on complete |
manual (#170) |
| — | modified | app/api/routers/chat_modules/stream_handler.py | Poll request.is_disconnected() every 8 chunks; on disconnect flip shared cancel flag so upstream provider thread stops (#170) |
manual (#170) |
| — | created | app/api/routers/chat_modules/stream_params.py | Extracted build_stream_params from stream_handler.py to stay under 200-line cap |
manual (#170) |
| — | modified | app/api/routers/chat.py | Pass FastAPI Request into handle_streaming_chat for disconnect polling (#170) |
manual (#170) |
| — | modified | app/resources/chat_modules/chat_class.py | Pipe _indoxhub_request_id into provider params on streaming chats (#170) |
manual (#170) |
| — | modified | app/providers/openai/chat_modules/_standard.py | Extract _indoxhub_request_id, forward to stream method (#170) |
manual (#170) |
| — | modified | app/providers/openai/chat_modules/_standard_stream.py | Inside sync-stream thread, check cancel event per chunk; await stream_response.aclose() + break on set (#170) |
manual (#170) |
| — | modified | docs/usage/streaming.md | Documented client-disconnect cancellation behavior and added chat /stop-stream endpoint alongside existing completions endpoint (#170) |
manual (#170) |
| — | created | docs/use-cases/model-comparison.md | New use-case page for parallel model comparison (Python + JS examples, usage parsing, Arena UI pointer) | manual |
| — | modified | app/api/routers/chat_modules/stream_billing.py | Added cost and latency_ms to response.done SSE usage payload (#171); refactored to call _compute_and_settle + settle_hold instead of bill_user |
manual (#171, #172) |
| — | created | app/api/routers/chat_modules/credit_hold.py | New module: estimate_hold_cost, place_hold, settle_hold, release_hold — atomic pre-deduction + reconcile (#172) |
manual (#172) |
| — | created | app/api/routers/chat_modules/stream_preflight.py | Extracted check_credits + place_stream_hold from stream_handler.py to stay under 200-line cap |
manual (#172) |
| — | modified | app/api/routers/chat_modules/stream_handler.py | Place hold pre-stream; release hold on error; use preflight module | manual (#172) |
| — | modified | app/utils/stream_manager.py | Added credit_holds: dict[str, Decimal] storage for per-stream pre-deductions (#172) |
manual (#172) |
| — | modified | app/providers/openai/chat_modules/_completions.py | Propagated #170 cancel_event + aclose pattern to OpenAI completions sync bridge | manual (#170) |
| — | modified | app/providers/openai/chat_modules/_responses_stream.py | Propagated #170 cancel_event + aclose pattern to OpenAI responses sync bridge | manual (#170) |
| — | modified | app/providers/xai/chat_modules/streaming.py | Propagated #170 cancel_event + aclose pattern to xAI | manual (#170) |
| — | modified | app/providers/qwen/chat_modules/streaming.py | Propagated #170 cancel_event pattern to Qwen | manual (#170) |
| — | modified | app/providers/deepseek/chat_modules/streaming.py | Propagated #170 cancel_event + aclose pattern to DeepSeek | manual (#170) |
| — | modified | app/providers/huggingface/chat_modules/streaming.py | Propagated #170 cancel_event + aclose pattern to HuggingFace | manual (#170) |
2026-04-19¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | created | scripts/capture_baseline.sh | Phase 0 observability capture script (10-min docker stats, ss -s, file-nr, ulimit, nginx stub_status via docker exec) | manual (SSE streaming plan) |
| — | created | docs/baseline/2026-04-19-pre-sse.md | Phase 0 pre-SSE baseline template (to be filled after running capture on prod) | manual (SSE streaming plan) |
| — | created | nginx/conf.d/stub_status.conf | Internal nginx stub_status on 127.0.0.1:81, allow 127.0.0.1; deny all | manual (SSE streaming plan) |
| — | modified | nginx/nginx.conf | Include stub_status.conf in http block | manual (SSE streaming plan) |
| — | modified | docs/plans/2026-04-19-sse-streaming.md | Fix path drift: Phase 1 compose path → docker/production/docker-compose.yml; Phase 8 nginx file → nginx/conf.d/prod/api.conf | manual (SSE streaming plan) |
| — | modified | scripts/capture_baseline.sh | Fix: per-row timestamps + docker stats --no-stream polling (was streaming mode writing ANSI + single end-time) | manual (SSE streaming plan) |
| — | modified | scripts/capture_baseline.sh | Fix: resolve app container by compose service+project labels (rollout-suffixed names like indoxhub-prod-indoxhub-server-58); re-resolve each stats tick | manual (SSE streaming plan) |
| — | modified | docs/baseline/2026-04-19-pre-sse.md | Fill with prod capture data (2026-04-19T20:59→21:09Z): ulimit 1024 both containers, app peak CPU 41.34% at startup, MEM 132 MB, nginx 5 concurrent / 6 req/min peak | manual (SSE streaming plan) |
| — | created | deploy/sysctl/99-indoxhub.conf, deploy/limits/indoxhub.conf | Phase 1 host sysctl + nofile limits; applied via PROD_setup.yml idempotent step | manual (SSE streaming plan) |
| — | modified | docker/production/docker-compose.yml, nginx/docker-compose.yml | Phase 1 ulimits nofile 65536 on indoxhub-server (prod compose) and router-nginx (nginx compose) | manual (SSE streaming plan) |
| — | modified | .github/workflows/PROD_setup.yml | Phase 1 add idempotent step: install sysctl/limits conf, run sysctl --system on change, echo effective values | manual (SSE streaming plan) |
04-17-2026¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | modified | app/resources/chat.py | Refactored 630→5-line re-export stub; split into chat_modules/ | manual |
| — | created | app/resources/chat_modules/init.py, chat_class.py, image_processing.py, message_processing.py, response_handling.py | Chat module split (534 total lines) | manual |
| — | modified | app/utils/model_info_mongo.py | Refactored 611→59-line re-export stub; split into model_info_mongo_modules/ | manual |
| — | created | app/utils/model_info_mongo_modules/init.py, cache.py, crud.py, loaders.py, queries.py | Model info module split (462 total lines) | manual |
| — | modified | app/api/routers/auth_core.py | Refactored 589→48-line thin router; split into auth_core_modules/ | manual |
| — | created | app/api/routers/auth_core_modules/init.py, login.py, logout.py, register.py, token.py | Auth core module split (533 total lines) | manual |
| — | modified | app/db/session_management.py | Refactored 581→31-line re-export stub; split into session_modules/ | manual |
| — | created | app/db/session_modules/init.py, create.py, device.py, lookup.py, manage.py | Session module split (481 total lines) | manual |
| — | modified | app/api/routers/user.py | Refactored 581→9-line router; split into user_modules/ | manual |
| — | created | app/api/routers/user_modules/init.py, api_keys.py, profile.py, usage.py | User module split (303 total lines) | manual |
| — | modified | app/db/get_daily_report.py | Refactored 564→5-line re-export stub; split into report_modules/ | manual |
| — | created | app/db/report_modules/init.py, analytics.py, builder.py, queries.py, template.py | Report module split (413 total lines) | manual |
| — | modified | app/providers/openai/helpers.py | Refactored 554→41-line re-export stub; split into helper_modules/ | manual |
| — | created | app/providers/openai/helper_modules/init.py, constants.py, formatters.py, messages.py, model_utils.py, reasoning.py | OpenAI helpers module split (445 total lines) | manual |
| — | modified | app/providers/anthropic/chat_handler.py | Refactored 542→5-line re-export stub; split into chat_modules/ | manual |
| — | created | app/providers/anthropic/chat_modules/init.py, handler.py, non_streaming.py, params.py, streaming.py | Anthropic chat module split (296 total lines) | manual |
| — | modified | app/api/routers/model.py | Refactored 537→8-line router; split into model_modules/ | manual |
| — | created | app/api/routers/model_modules/init.py, json_loader.py, model_endpoints.py, provider_endpoints.py | Model module split (258 total lines) | manual |
04-16-2026¶
| # | Item | Commit | Status |
|---|---|---|---|
| 1 | Contributing page removed from nav | fix: re-apply 429 RateLimitError exception handler (bundled) |
✅ Done |
| 2 | 429 RateLimitError handler | fix: re-apply 429 RateLimitError exception handler |
✅ Done |
| 3 | docs/why-indoxhub.md |
fix: re-create why-indoxhub.md and add to nav |
✅ Done |
| 4 | docs/usage/pricing.md |
fix: re-create pricing.md and add to nav |
✅ Done |
| 5 | docs/usage/rate-limits.md |
fix: update rate-limits.md with real tier numbers and fixed time windows |
✅ Done |
Remaining from the damage report:
| # | Item | Action |
|---|---|---|
| 6 | tests/test_billing_fixes.py |
Re-create |
| 7 | Pre-flight credit check | Re-apply |
| 8 | Endpoint-specific minimums | Re-apply |
| 9 | Block negative credits | Re-apply |
| 10 | Fail-closed unknown pricing | Re-apply |
| 11 | STT duration estimate | Re-apply |
| 12 | 5% API markup | DO NOT re-apply |
16-04-2026¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| 23:30 | modified | mkdocs.yml | Added git-revision-date-localized plugin with custom date format (MM-DD-YYYY), added repo_url/repo_name |
manual |
| 23:30 | modified | 29 docs/*.md files | Removed manual *Last updated: YYYY-MM-DD* lines — dates now auto-generated from git history |
manual |
04-07-2026¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | modified | docs/deployment.md, docs/provider-integration.md, docs/stripe-tax-setup.md | Fixed IndoxRouter → IndoxHub branding references | /mkdocs-material |
| — | created | docs/getting-started.md | New getting started guide with multi-language examples | /mkdocs-material |
| — | created | docs/usage/basic-usage.md, docs/usage/chat.md, docs/usage/completions.md, docs/usage/embeddings.md, docs/usage/images.md, docs/usage/video.md, docs/usage/tts.md, docs/usage/stt.md, docs/usage/models.md, docs/usage/streaming.md, docs/usage/vision.md, docs/usage/byok.md, docs/usage/responses.md, docs/usage/tracking.md, docs/usage/rate-limits.md | Full usage guide with request/response schemas, multi-language tabbed examples (Python/JS/cURL/OpenAI SDK) | /mkdocs-material |
| — | created | docs/examples/basic.md, docs/examples/advanced.md, docs/examples/openai-sdk.md | Example pages — basic, advanced patterns, OpenAI SDK compatibility guide | /mkdocs-material |
| — | created | docs/api-reference/api-reference.md, docs/api/client.md, docs/api/responses.md, docs/api/exceptions.md | API reference — endpoints summary, client methods, response schemas, error codes | /mkdocs-material |
| — | created | docs/use-cases/chatbots.md, docs/use-cases/rag-systems.md, docs/use-cases/content-generation.md, docs/use-cases/document-processing.md | Use case guides — chatbots, RAG, content generation, document processing | /mkdocs-material |
| — | modified | docs/README.md | Updated homepage with all capabilities, providers list, and new nav links | /mkdocs-material |
| — | modified | mkdocs.yml | New nav structure with Usage Guide, Examples, API Reference, Use Cases sections; added meta plugin and attr_list extension | /mkdocs-material |
| — | created | mkdocs.yml | MkDocs config with Material theme, SEO plugins (search, meta, sitemap), nav structure | manual |
| — | created | docs/overrides/main.html | Template override with OG and Twitter Card meta tags for SEO | manual |
| — | created | docs/assets/og-image.png | 1200x630 OG image — dark theme with provider tags | manual |
| — | modified | docs/README.md, docs/api-reference.md, docs/architecture.md, docs/auth-endpoints.md, docs/configuration.md, docs/database-schema.md, docs/deployment.md, docs/contributing.md, docs/provider-integration.md, docs/stripe-integration.md, docs/stripe-tax-setup.md, docs/BYOK_IMPLEMENTATION.md, docs/ci-cd-setup.md | Added SEO front matter (title + description) to all doc pages | manual |
| — | modified | mkdocs.yml | Removed meta/sitemap plugins (require extra packages), added exclude_docs for plans/tasks, added Project nav section | /review |
| — | modified | docs/overrides/main.html | Added fallback guard for canonical_url on error pages | /review |
| — | modified | docs/changelog.md | Added front matter for SEO | /review |
| — | modified | docs/issues.md | Added front matter for SEO | /review |
| — | modified | docs/README.md | Fixed dead link: authentication.md → auth-endpoints.md | /review |
| — | modified | .github/workflows/GLOBAL_lint.yml | Added docs-build job — runs mkdocs build --strict on every push | manual |
04-01-2026¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| 12:00 | created | .claude/skills/push-changelog/SKILL.md | Added push-changelog skill adapted for IndoxHub FastAPI backend | manual |
| 12:00 | created | .claude/skills/test-suite/SKILL.md | Added test-suite skill adapted for FastAPI/Pytest testing | manual |
| 12:00 | modified | .claude/WORKFLOW.json | Updated workflow to include push-changelog and test-suite skills | manual |
| 12:00 | created | docs/changelog.md | Created changelog file for tracking changes | manual |
2026-04-18¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | created | app/api/routers/model_modules/trending_helpers.py | Extracted stats/featured/flagship helpers (kept endpoint under 200-line limit) | manual |
| — | modified | app/api/routers/model_modules/model_endpoints.py | /trending now auto-injects first non-disabled text_completions entry from anthropic/openai/google so newly-added flagship models (e.g. Opus 4.7) surface immediately without admin action | manual |
2026-04-19¶
| Time | Action | Files | Details | Skill |
|---|---|---|---|---|
| — | modified | app/core/config_fields.py | Added RESEMBLE_API_KEY, RESEMBLE_BASE_URL, RESEMBLE_SYNTH_URL settings | manual |
| — | created | app/providers/resemble/init.py, client.py, errors.py, tts_handler.py, voices_handler.py, resemble_provider.py | Resemble AI provider Phase 1 scaffold — TTS sync + list/get voices, no billing yet | manual |
| — | created | tests/providers/init.py, test_resemble_client.py, test_resemble_tts.py, test_resemble_voices.py | Phase 1 unit tests (21 tests, all passing) — mocked httpx, error mapping, happy/auth/429/5xx paths | manual |
| — | created | app/providers/resemble/stt_handler.py, audio_job_handler.py | Phase 2: STT create/get/list/query + shared async-job handler for /audio_enhancements and /edit |
manual |
| — | modified | app/providers/resemble/resemble_provider.py | Expose Phase 2 handlers (create/get/list for transcript, enhancement, edit; query_transcript); extend capabilities list | manual |
| — | created | tests/providers/test_resemble_stt.py, test_resemble_audio_jobs.py | Phase 2 unit tests (19 tests, all passing) — STT CRUD, query, enhancement/edit create/get/list, 401/429/5xx paths | manual |
| — | created | app/providers/resemble/crud_handler.py, clips_handler.py, recordings_handler.py, provider_phase3_mixin.py | Phase 3: Projects (generic CRUD), Clips (nested + timestamps), Recordings (nested). Mixin keeps provider under 200-line cap | manual |
| — | modified | app/providers/resemble/resemble_provider.py | Wire Phase 3 handlers; add Phase3Mixin; extend capabilities list | manual |
| — | created | tests/providers/test_resemble_content.py | Phase 3 unit tests (19 tests, all passing) — Projects/Clips/Recordings CRUD + timestamps + 401/429/5xx | manual |
| — | created | app/providers/resemble/safety_job_handler.py, watermark_handler.py, identity_handler.py, provider_phase4_mixin.py | Phase 4: deepfake detection (audio/video/image), intelligence, audio-source-tracing, watermark apply/detect, identity search + CRUD (beta) | manual |
| — | modified | app/providers/resemble/resemble_provider.py | Wire Phase 4 handlers + mixin; extend capabilities list with detection/intelligence/tracing/watermark/identity | manual |
| — | created | tests/providers/test_resemble_safety.py | Phase 4 unit tests (22 tests, all passing) — covers audio/video/image modalities, watermark apply+detect pair, identity CRUD, 401/429/5xx | manual |
| — | modified | app/providers/resemble/voices_handler.py | Phase 5: add create_voice / build_voice / delete_voice to existing handler (no new file — avoid duplication) | manual |
| — | created | app/providers/resemble/voice_design_handler.py | Phase 5: POST /voice-design + POST /voice-design/{uuid}/{idx}/create_rapid_voice | manual |
| — | modified | app/providers/resemble/resemble_provider.py | Wire Phase 5 (5 new methods inline — too small to justify a mixin); add voice_cloning/voice_design capabilities; note Business-plan requirement in docstring | manual |
| — | created | tests/providers/test_resemble_voice_creation.py | Phase 5 unit tests (11 tests, all passing) — voice cloning CRUD, voice design two-step, Business-plan 403 path, 429/5xx | manual |
| — | created | app/providers/resemble/agents_extras_handler.py, knowledge_base_handler.py, provider_phase6_mixin.py, unsupported_mixin.py | Phase 6: agents CRUD (reuses ResembleCRUDHandler) + capabilities/system-tools catalog, agent tools CRUD, webhooks CRUD, KB CRUD + attach/detach/reingest. Phone numbers + dispatch permanently skipped (Twilio dep) | manual |
| — | modified | app/providers/resemble/resemble_provider.py | Wire Phase 6 handlers + mixin; MRO fix (unsupported mixin placed before BaseProvider so ABC overrides resolve); extend capabilities list | manual |
| — | created | tests/providers/test_resemble_agents.py | Phase 6 unit tests (20 tests, all passing) — agents CRUD, capabilities/system-tools, tools+webhooks CRUD reuses, KB attach/detach/reingest, unsupported-mixin regression test, 401/429/5xx | manual |
| — | created | docs/plans/RESEMBLE_PRODUCTION_READINESS_PLAN.md | Captures the full gap between Phases 1-6 (SDK-only, 112 tests mocked) and production-ready. Lists 18 concrete blockers, all 8 unanswered open questions from original plan §6, proposed Phases 7-14 (DB+billing, routes, file upload, webhooks+reconciliation, contract tests, admin UI, resilience, rate-limit fairness), merge strategy options, permanently-skipped items to reaffirm, and first actions for next session | manual |