chore(deps): bump aes-gcm from 0.10.3 to 0.11.0 - #180
Conversation
- 4-crate Cargo workspace (core, api, cli, mcp) - SQLite schema: accounts, posts, schedules, comments, analytics, media, rate_tracking - Axum HTTP server with 20+ route handlers (stubbed) - Clap CLI with 7 command groups (account, post, schedule, comment, analytics, media, token-check) - MCP server (stdio JSON-RPC) with 13 tools declared - DESIGN.md: full architecture specification - Dockerfile (cargo-chef multi-stage) - GitHub Actions CI (fmt, clippy, test, build)
… API, CLI, MCP - titen-core: Threads Graph API client (publish, insights, comments, token refresh) - titen-core: Scheduler (tokio-cron-scheduler) for scheduled posts - titen-core: Sentiment engine (stub + keyword-based) - titen-core: S3 storage via reqwest (generic S3-compatible) - titen-api: All route handlers wired to real store/Threads operations - titen-api: API key auth middleware (X-API-Key header) - titen-api: Extracted lib.rs for CLI re-use - titen-cli: All commands call API via reqwest client - titen-cli: Added api.rs helper module - titen-mcp: Full tools/call dispatch to store operations (10 tools) - All clippy clean, fmt clean, compiles with zero warnings
- titen-core: 44 unit tests (sentiment, error, models, compute_summary) - titen-api: 15 integration tests (accounts/posts/schedules CRUD) - README.md: full docs with setup, CLI, API, MCP, Docker - Crate-level /// docs for all 4 crates - All 59 tests pass, clippy clean, fmt clean
- Fix container/publish URLs: me -> /{threads_user_id}/threads*
- Fix insights: use /{id}/insights?metric= edge format
- Add reply management: create, hide, sentiment
- Add carousel support (3-step container flow)
- Add topic_tag, link_attachment, gif_attachment params
- Add user insights endpoint
- Add user profile retrieval
- Add publishing limit check
- Add keyword search
- Add new models: ContainerStatus, UserProfile, PublishingLimit,
InsightMetric, UserInsightMetric, LinkTotalValue, CreateReply
- Update API routes and MCP tools for all new features
- From<Vec<InsightMetric>> impl for backwards-compatible Insights
- New config module with env var consts, default values, helper fns - Default DB path: ~/.codecoradev/titen/titen.db (auto-creates dir) - Default host: 0.0.0.0, port: 7845, URL: http://localhost:7845 - All 4 binaries (api, cli, cli/serve, mcp) now import from one source - Eliminates 4x duplicated hardcoded defaults
…esh tokens - Remove refresh_token from Account/CreateAccount/UpdateAccount/DB (Threads API uses access_token only for refresh, no separate token) - Add 002 + 003 migrations (drop refresh_token, add app_secret) - Auto-resolve user_id + username from /me when adding account - Auto-exchange short-lived → long-lived token when app_secret provided - Add ensure_valid_token() auto-refresh guard (refresh if expiring/expired) - Add exchange_long_lived_token() for short→long exchange - Add resolve_account() to fetch user_id+username from access_token - Simplify CLI: accounts add --token [TOKEN] (username/user_id optional) - Clean up DRY: remove all refresh_token references from store queries
- Multi-stage Rust build (builder → slim runtime) - Exposes titen-api (7845), titen-cli, titen-mcp binaries - docker-compose with volume mount for persistent DB - Health check at /health (skip auth) for Traefik/CF Tunnel
- Fix binary name: titen-cli -> titen (matches Cargo output) - Add VERSION ARG + OCI labels to Dockerfile - Add production image comment to docker-compose.yml - Add GitHub Actions release workflow (verify-main -> build 3 arch -> release + Docker push GHCR/DockerHub) - Add binaries/ to .gitignore - Matches uteke Docker pattern (CI binary download, multi-stage, non-root, healthcheck)
- Split Check & Lint into separate Check, Format, Clippy jobs - Add --all-targets to check and clippy - Add RUST_BACKTRACE=1 - Remove toolchain pin (use stable like uteke) - Remove build dependency on check/test (all parallel) - Add push trigger on main branch
- Remove unused imports: routing::{delete, post} (used as methods, not functions)
- Remove unused import: tower::ServiceExt
- Prefix unused variable with underscore: _account
feat: fix Docker files + add release workflow
- Security: cargo-audit + trivy daily scan (matches uteke pattern) - Cora AI code review on PR to develop/main - Triggers: push, PR, schedule (06:00 UTC), manual dispatch
feat: add security + code review workflows
- Fix SQL injection in list_posts() and list_schedules(): replace format!() string interpolation with parameterized ? binds - Fix timing attack on API key auth: replace == with subtle::ConstantTimeEq constant-time comparison - Fix access_token exposure in API responses: add safe_account_json() helper, strip token from create/update/refresh - Fix CORS permissive() default: add TITEN_CORS_ORIGINS env var (comma-separated), fallback to permissive - Fix migration crash on restart: all 14 CREATE INDEX now use IF NOT EXISTS Verified: build clean, 59 tests pass, clippy -D warnings, fmt ok
fix: security hardening — SQL injection, timing attack, token leak, CORS
Release workflow extracts Linux binaries to binaries/ directory before Docker build, but .dockerignore was blocking COPY binaries/ in Dockerfile.
fix: remove binaries/ from .dockerignore for CI Docker builds
libssl3t64 is a Trixie-only package, not available in Bookworm. Matches uteke Dockerfile which uses trixie-slim.
fix: upgrade Dockerfile base to debian:trixie-slim
…-8b) (#155) ## What - SQLite pool max_connections now reads from TITEN_DB_MAX_CONNECTIONS env var - Defaults to 5 if unset or invalid (backward compatible) ## Why - Production deployments may need more/fewer connections based on load - Hardcoded value was inflexible for different deployment scenarios ## Testing - cargo test -p titen-api: ALL PASS Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
* fix: security hardening — 7 audit findings (#157-#163) ## What - #157: Escape single quotes in VACUUM INTO path (SQL injection fix) - #158: Default bind 127.0.0.1 instead of 0.0.0.0 - #159: Normalize auth bypass path (trim trailing slash) - #160: /metrics requires auth unless TITEN_PUBLIC_METRICS=true - #161: Restore warning to stop server first - #162: Pre-restore backup uses timestamp instead of fixed name - #163: Remove CLA requirement from CONTRIBUTING.md ## Why Cora + GHAS review bots flagged these issues on PRs #150-#154. SQL injection and default bind were critical/medium security concerns. ## Changes - crates/titen-cli/src/main.rs: VACUUM escape + restore warning + timestamp - crates/titen-cli/src/lib.rs: default host 127.0.0.1 - crates/titen-api/src/server.rs: path normalization + metrics auth toggle - crates/titen-cli/tests/cli_parsing.rs: update default host assertion - CONTRIBUTING.md: remove CLA section ## Testing - cargo test --workspace: ALL PASS (0 failures) - cargo clippy: 0 warnings * fix: address Cora review — path allowlist + OnceLock for env var - Replace quote escaping with strict character allowlist for VACUUM INTO path (alphanumeric + / - _ . only). Reject unsafe paths with clear error. - Use OnceLock for TITEN_PUBLIC_METRICS to avoid env scan on every request. * fix: allow spaces in backup path validation allowlist * fix: add Windows path support (\, :) to backup validation allowlist * docs: add CRITICAL comment on SQL injection prevention in allowlist --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
* feat(v0.7.1): token auto-refresh in MCP + titen status command Token expiry auto-refresh: - Add ensure_valid_token call to 7 MCP handlers that hit Threads API - Handlers: get_user_profile, get_publishing_limit, fetch_comments, get_post_insights, fetch_mentions, search_keyword, reply_to_comment - Previously only scheduler refreshed tokens — MCP would fail on expired tokens titen status command: - New CLI command showing system overview via direct SQLite access - Displays: version, DB info, account counts, token health, content counts - Per-account token expiry with remaining time - Health summary: HEALTHY / WARNING / DEGRADED - No server required — reads DB directly Test: test_status added to CLI parsing suite (28 tests pass) * fix: surface DB errors instead of unwrap_or_default in status command CodeCora review: unwrap_or_default/unwrap_or(0) silently hides DB errors, reporting 0 counts even when accounts exist. Replace with ? operator for proper error propagation. * fix: ensure pool.close() always runs in status command CodeCora review: early return via ? operator skips pool.close(), potentially leaving SQLite WAL/journal files locked. Restructured to extract query logic into query_status_data() helper, then always close pool before propagating errors. --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Restructure CONTRIBUTING.md to match Uteke's mature format — adds 'What makes a good contribution', 'Keep changes focused', 'Discuss first', 'What Titen is not', and FAQ sections. Preserves Titen-specific content (frontend/bun workflow, multi-crate architecture, MCP tools, token encryption, database migrations). Update issue templates to Uteke format — structured OS dropdown, version input field, 'willing to contribute' dropdown on feature requests. Keep Titen component list (titen-core/api/cli/mcp/web). Fix PR template Cora link to cora-cli repo. Add dependabot.yml for cargo, github-actions, and docker ecosystem weekly updates. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
|
🔍 Cora AI Code ReviewReview powered by cora-code · BYOK · MIT |
* fix(oauth): add APP_URL fallback for redirect URI derivation
OAuth login was failing with error 4476001 ("No redirect present in URI")
because derive_redirect_uri() returned an empty string when neither
TITEN_OAUTH_REDIRECT_URI nor TITEN_ALLOWED_HOSTS was set.
APP_URL is already documented as 'Public URL of the web frontend (used for
OAuth redirect URIs)' in .env.example but was not actually used for this
purpose. Now it serves as a fallback between explicit override and the
strict Host-header allowlist.
Resolution order:
1. TITEN_OAUTH_REDIRECT_URI (explicit, safest)
2. APP_URL + /auth/callback (trusted config, most deployments use this)
3. Host header allowlist (strict, requires TITEN_ALLOWED_HOSTS)
Also documents TITEN_OAUTH_REDIRECT_URI and TITEN_ALLOWED_HOSTS in
.env.example — they were completely undocumented before.
* fix(oauth): enforce HTTPS for APP_URL redirect URI derivation
CodeCora review: APP_URL blindly trusted for scheme. Non-HTTPS redirect
URIs are insecure for OAuth (code interception over plaintext). Now
requires https:// for production, allows http:// only for localhost dev.
---------
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
d914243 to
d20986e
Compare
… fallback (#184) Two-layer fix for OAuth 'No app ID' / 'No redirect URI' errors: 1. docker-compose.yml: Pass APP_URL env var to API container, not just web. Previously APP_URL only reached the web container (as ORIGIN), leaving the API container unable to derive redirect_uri from env. 2. Frontend (accounts/+page.svelte): When backend returns app_id but no authorize_url (redirect_uri empty), construct the authorize URL client-side using window.location.origin — more reliable than the internal Docker Host header that derive_redirect_uri() sees. 3. Backend (settings.rs): Return null authorize_url when redirect_uri is empty, instead of generating a broken URL with empty redirect_uri=. This signals the frontend to use the client-side fallback path. Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
d20986e to
3ac455a
Compare
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
3ac455a to
8867421
Compare
…#187) * fix(media): s3_url returns full absolute URL instead of relative path #186: Media uploads stored relative paths (e.g. '/2026/08/12/uuid.png') instead of full URLs, causing broken image previews and Threads API publish failures. Root cause: empty-string TITEN_S3_PUBLIC_URL env var was treated as Some('') instead of None, producing format!('{}/{key}', '') = '/{key}'. Fix layers (defense-in-depth): - storage.rs: empty-string guard in from_env(), trailing slash trim in get_url() and object_url() - media.rs: read-time heal_media_urls() repairs legacy relative URLs in DB on list_media response (safety net for existing data) - schedules.rs: create/patch/update validators reject non-absolute media_urls with 400 INVALID_MEDIA_URL - .env.example: document TITEN_S3_PUBLIC_URL semantics + empty-string warning 6 new unit tests covering all heal scenarios. 176 total tests pass. * refactor(media): use shared build_public_url to eliminate logic duplication CodeCora review on #187: heal_media_urls duplicated S3Storage URL construction logic. Extracted S3Storage::build_public_url() as single source of truth, now called by both get_url() and heal_media_urls(). * fix(media): guard empty bucket in heal_media_urls early exit Cora review: collapsed nested if + guard against malformed URL when bucket is empty but endpoint is set. Now requires public_url OR (endpoint + bucket) before attempting reconstruction. * refactor(tests): eliminate env var mutation in heal_media_urls tests CodeCora review: parallel test env var mutation causes race conditions. Extracted heal_media_urls_with() as pure function that accepts config params directly — tests now deterministic without touching global state. Added 2 new edge case tests: - heal_noop_without_storage_config - heal_uses_public_url_when_bucket_empty --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
8867421 to
8c15e66
Compare
Security: prevent accidental token leakage when user_id field contains a leaked access token instead of a numeric Threads ID. Backend (accounts.rs): - safe_account_json() now masks user_id values >50 chars (token-like) to null, with a tracing::warn log for audit trail - Added 5 unit tests covering: normal ID, short alphanumeric, token, empty string, and access_token never exposed Frontend (accounts/+page.svelte): - Truncate user_id display to 12 chars + ellipsis if >30 chars as defense-in-depth against any future leakage Root cause: ajianaz account has 233-char base64 string in user_id (likely from manual account creation bug pre-#116 OAuth fix). Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…#189) Problem: /accounts page only showed username + token expiry — no avatar, bio, or follower count. Dashboard followers/following/media_count were always 0 because Threads API does not return these fields on the /me profile node. Fix: - BE: get_user_profile now fetches profile + followers_count concurrently (tokio::join), merging the insight value into the response - BE: UserProfile struct gains optional followers_count field - FE: /accounts table enriched with avatar, name, bio, followers count (lazy-loaded per account, best-effort with skeleton loading states) Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Bumps [aes-gcm](https://github.com/RustCrypto/AEADs) from 0.10.3 to 0.11.0. - [Commits](RustCrypto/AEADs@aes-gcm-v0.10.3...aes-gcm-v0.11.0) --- updated-dependencies: - dependency-name: aes-gcm dependency-version: 0.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
8c15e66 to
98ce4d1
Compare
|
OK, I won't notify you again about this release, but will get in touch when a new version is available. If you'd rather skip all updates until the next major or minor version, let me know by commenting If you change your mind, just re-open this PR and I'll resolve any conflicts on it. |
Bumps aes-gcm from 0.10.3 to 0.11.0.
Commits
a10b56faes-gcm v0.11.0 (#852)f042e9caead-stream v0.6.0 (#851)b29735aAdopt Trusted Publishing (#854)a1fe43fxaes-256-gcm: enable and fix workspace level lints (#850)8cf876feax: remove toplevel lint attributes (#849)4661ddfocb3: enable and fix workspace-level lints (#848)c821431eax: enable and fix workspace-level lints (#847)d3684bbdeoxys: enable and fix workspace-level lints (#846)5e016e2chacha20poly1305: enable and fix workspace-level lints (#845)b3524d3ccm: enable and fix workspace-level lints (#844)