552 Commits

Author SHA1 Message Date
metatroncubeswdev
7816b4d2be Merge main: add the real public quick-audit endpoint for crawlerx.co
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-20 19:19:21 -04:00
metatroncubeswdev
510c46e5ed Add a real, rate-limited public quick-audit endpoint for crawlerx.co
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
The marketing site's "Run Live Audit" widget was entirely fake: it looked
up a canned preset or a generic templated result for any domain typed in,
after a scripted delay. This adds /api/public/quick-audit, which crawls
the submitted URL with the same crawler + HTML analyzer the authenticated
product uses, and reports one real finding (or an honest error if the
site is unreachable/blocked) instead of ever fabricating one. Per-IP and
global daily KV caps bound the cost of anonymous abuse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-20 19:19:12 -04:00
metatroncubeswdev
bed11be657 Merge main: replace the actual logo asset (crawlerx-mark.png was MetatronCube's cube) 2026-10-18 21:05:14 -04:00
metatroncubeswdev
8e3a9f2882 Replace the actual logo asset — crawlerx-mark.png was MetatronCube's cube
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
The previous commit pointed every <img> at crawlerx-mark.png instead of
transparent-logo.png, but both files are byte-for-byte the same
MetatronCube glass-cube artwork — the Oct-era rebrand renamed the file,
it never replaced the image. So the logo never actually changed anywhere
in the real app, despite every component referencing the "right" filename.

Added the real CrawlerX mark (the teal/amber check-and-arrow symbol
already used on the marketing site) as public/crawlerx-logo.svg and
repointed every logo reference at it.

Also: the favicons and apple-touch-icon were a literal pine tree (unrelated
leftover asset, not MetatronCube or CrawlerX), and the webmanifest's
theme_color was still MetatronCube blue. Regenerated all icon sizes from
the real mark and fixed the manifest color.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-18 21:05:08 -04:00
metatroncubeswdev
368c82ee4e Merge main: finish CrawlerX rebrand (theme tokens, sign-in page, logo refs) 2026-10-18 17:56:48 -04:00
metatroncubeswdev
0e8bfa1fa1 Finish the CrawlerX rebrand: theme tokens, sign-in page, stray logo refs
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
The Oct-era rebrand commit swapped the sidebar/app-shell logo and most
daisyUI component colors, but missed several spots:

- app.css's "crawlerx" / "crawlerx-dark" theme tokens were still the old
  MetatronCube blue (#3779b9) instead of the brand guide's teal (#0E6E6A).
  Every daisyUI-token-based component (most of the app) now gets the
  correct color with this one change.
- AuthPage.tsx (sign-in/sign-up) was untouched by the token system: a
  mountain-climber stock photo background, "Metatroncube / Solutions"
  wordmark, blue/cyan gradients, generic value props, and a stray
  alt="Metatroncube" on the logo. Replaced with the brand gradient, the
  CrawlerX mark, on-brand copy and value props, and the real color tokens
  instead of hardcoded Tailwind blue/cyan classes.
- Four more components (onboarding chat, post-signup onboarding, the
  OAuth consent screen, the subscribe page) still pointed their logo
  <img> at /transparent-logo.png instead of /crawlerx-mark.png.
- PricingGraphics.tsx (the decorative cube/chart illustration on the
  subscribe page) had ~17 hardcoded MetatronCube-blue hex values; remapped
  the whole palette to the CrawlerX teal family.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-18 17:56:40 -04:00
metatroncubeswdev
20361f3451 Merge main: branding fix, Autumn local-ledger guards, JSON 404 fix 2026-10-18 01:37:00 -04:00
metatroncubeswdev
336db032a4 Return JSON, not plain text, from the Autumn route's 404
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
autumn-js's client hooks call response.json() on every response regardless
of status. The plain-text "Not found" body from the previous commit's guard
made that throw a SyntaxError client-side ("Unexpected token 'N'...") in
hosted mode once Autumn-dependent UI actually mounted and called it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-18 01:36:42 -04:00
metatroncubeswdev
9298f67c7f Stop Autumn-only code paths throwing in local-ledger billing mode
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Two call sites still hard-required AUTUMN_SECRET_KEY regardless of billing
mode: the /api/autumn/$ route (autumn-js's client-side hooks hit it after
sign-up/on billing screens) and getBillingUsageEvents (Autumn's per-event
usage history). Both now degrade gracefully — 404 and an empty list,
respectively — when Autumn isn't configured, the same way subscription.ts's
credit checks already do, instead of autumn-js throwing "secret key not
found" once a request actually reaches it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 21:31:30 -04:00
metatroncubeswdev
78d0aaad0c Fix hardcoded "OpenSEO" app name in transactional emails
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Verification, invitation, and password-reset emails always said
"OpenSEO" regardless of which product/brand is actually deployed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 21:28:49 -04:00
metatroncubeswdev
4f52d02df1 vite.config.ts: use loadEnv() instead of bare process.env
process.env inside defineConfig() only sees whatever the OS process
environment already has — it does not automatically contain a project's
.env file contents just because Vite loads that file elsewhere (envPrefix
only reaches import.meta.env in app code, a separate mechanism). The
previous commit's PORT/ALLOWED_HOST read from process.env worked only by
coincidence of how a process happened to be launched, and silently did
nothing when it wasn't. loadEnv() is Vite's own documented API for reading
.env files inside the config itself, independent of the launch method.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 20:09:51 -04:00
metatroncubeswdev
bed0504418 vite.config.ts: actually read PORT/ALLOWED_HOST from env
Both were documented self-host knobs (SELF_HOSTING_DOCKER.md, compose.yaml)
but hardcoded to port 3001 and seo.thedomainnest.com instead, so any second
instance on a different port/domain got either a port clash or Vite's
preview host-check ("Blocked request... not allowed"). Defaults preserve
exact current behavior for deployments that don't set these.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 19:55:16 -04:00
metatroncubeswdev
324c9e064b Revert "vite.config.ts: actually read PORT/ALLOWED_HOST from env"
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
This reverts commit 1146dc2f6a9c8551007c3761f3539fb73c619800.
2026-10-17 19:55:01 -04:00
metatroncubeswdev
1146dc2f6a vite.config.ts: actually read PORT/ALLOWED_HOST from env
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Both were documented self-host knobs (SELF_HOSTING_DOCKER.md, compose.yaml)
but hardcoded to port 3001 and seo.thedomainnest.com instead, so any second
instance on a different port/domain got either a port clash or Vite's
preview host-check ("Blocked request... not allowed"). Defaults preserve
exact current behavior for deployments that don't set these.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 19:49:21 -04:00
metatroncubeswdev
65a01af4d3 Fix critical billing bugs, add local usage caps, publish sales demo
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Three launch blockers from the Oct 17 direct-Stripe billing work:

- verifyStripeCheckoutSession defaulted an unconfirmed checkout session
  to "active"/isPaying:true, and had no billing permission check, so an
  abandoned (unpaid) checkout marked the org as a paying subscriber for
  free. Now defaults to "incomplete" and only trusts a real subscription
  status or a confirmed paid payment_status; also pins org id to the
  caller's own organization instead of trusting session metadata.
- The Stripe webhook fell back to parsing an unsigned request body as a
  real event whenever STRIPE_WEBHOOK_SECRET was unset, letting anyone POST
  a fake checkout.session.completed and grant any org a paid plan.
  STRIPE_WEBHOOK_SECRET is now required; unsigned requests are refused.
  Also maps Stripe's subscription.status properly (trialing counted as
  active) instead of collapsing anything but "active" to "canceled".
- meterDataforseoCall and every credit-check in subscription.ts skipped
  all usage metering/capping whenever AUTUMN_SECRET_KEY was unset — which
  is exactly the mode the Oct 17 work introduced for self-host direct
  Stripe billing. Added a local per-org monthly usage ledger
  (usage_ledger table, sqlite + pg) checked against each plan's monthly
  data budget (src/shared/crawlerxPlanBudgets.ts, from the PRD's unit
  economics table) so DataForSEO spend is capped even without Autumn.

Also: documented STRIPE_SECRET_KEY/STRIPE_WEBHOOK_SECRET/AUTUMN_SECRET_KEY
in .env.example, and published the CrawlerX product demo as a static page
at /demo.html (self-contained, no backend dependency).

Verified: tsc --noEmit clean, schema-parity test green, full vitest suite
green except two pre-existing unrelated failures (confirmed via stash),
knip/oxlint show no new findings over the pre-change baseline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-17 16:24:38 -04:00
Alaguraj0361
98694c56ea docs: add comprehensive work changelog and architecture documentation for Oct 17
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
2026-10-17 20:01:03 +05:30
Alaguraj0361
5d5484c0b0 add subscription billing flow and Stripe integration components
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
2026-10-17 19:58:12 +05:30
Alaguraj0361
df5f593369 add billing and subscription management system with Stripe integration
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
2026-10-17 19:40:15 +05:30
Alaguraj0361
5ae39ebfd4 add authentication routes, components, and styling for CrawlerX app
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
2026-10-17 15:02:39 +05:30
metatroncubeswdev
a3b13a112a Add agency edition implementation plan for team handover
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
16-week plan for taking the CrawlerX fork to external agency sales:
decisions, phased tasks with code pointers, risks, and a handover
checklist. Provided as Markdown and a standalone HTML page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 12:24:38 -04:00
metatroncubeswdev
05e64ccd36 Add combined SEO report: Search Console + Analytics + Site Audit in one view
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Per-project overview pulling together GSC performance totals/top queries,
GA4 organic overview metrics, and the latest completed site audit summary
into a single page under /p/$projectId/report. Each section degrades
independently (not connected / error / ok) so a missing integration never
blocks the rest of the report. Includes a "Download PDF" button that uses
window.print() against print-aware layout classes added to AppShell so the
app chrome is hidden and content flows naturally when printed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 14:37:11 -04:00
metatroncubeswdev
6d40767d95 Site audit: DataForSEO OnPage fallback for bot-blocked crawls
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Explicit, user-triggered button ("Get report from DataForSEO") shown when
the native crawler is blocked — never an automatic retry. DataForSEO's
OnPage API crawls from its own infrastructure with JS rendering, which
clears blocks a plain fetch() from our server can't.

- audits.crawlSource ("native" | "dataforseo") + dataforseoTaskId columns.
- dataforseo/onpage.ts: task_post (JS rendering + store_raw_html) / summary
  polling / pages listing / raw_html retrieval. Only task_post is billed
  (~$0.00125/page); the rest are free reads of already-billed results, per
  DataForSEO's pricing docs.
- DataForSeoAuditService: hard quota of 5 runs per project per calendar
  month, enforced server-side via the activity log (audit.dataforseo_report)
  before any DataForSEO spend — a rejected 6th run never reaches the API.
- Reuses the native pipeline instead of duplicating it: extracted
  buildAnalyzedPageResult() out of crawlPage() so both sources feed the same
  analyzeHtml -> runPageReporters -> runMultipageChecks -> auditPages/
  auditIssues path. No Cloudflare Workflow backs these audits; the existing
  getAuditStatus poll (already running every 3s while "running") drives an
  advance step each call instead.
- Known gap: broken-internal-link and orphan-page checks are native-only
  (they read the crawl's link graph from the AuditScratchpad Durable Object,
  which only the native crawl populates).
- UI: page-limit picker (25-500) + live quota display on the existing
  "blocked" screen.

Migration: drizzle/0046_*, drizzle-pg/0024_*.

tsc / oxlint / knip clean. New onpage.test.ts (7) + DataForSeoAuditService
.test.ts (5, including the quota-rejection path); full suite otherwise
unchanged (1195 pass, pre-existing samSkills Windows-CRLF failure only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 11:49:54 -04:00
metatroncubeswdev
17dfca406f Audit crawler: send a browser navigation header set (tier-1 anti-bot)
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
The crawler identified as `OpenSEO-Audit/1.0` with almost no headers, which
naive bot filters and security plugins block outright.

- New crawl-request.ts: AUDIT_USER_AGENT (a current Chrome string),
  buildAuditHeaders() (Accept, Accept-Language, Sec-Fetch-*, Sec-Ch-Ua,
  Upgrade-Insecure-Requests), and fetchForAudit() — fetch + those headers +
  one retry on a transient 429/503.
- Wired into the page crawl (site-audit-workflow-helpers), robots.txt +
  sitemap discovery, and start-URL redirect probing.

Gets past the naive tier; still reported as "blocked" for JS/TLS challenges
(Cloudflare Managed Challenge, DataDome) — those need a real browser. Doc note
points operators at WAF IP/UA allowlisting for their own sites.

No env dependency (keeps the audit lib importable without a cloudflare:workers
mock). tsc / oxlint / knip clean; new crawl-request.test.ts (5); suite
otherwise unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 16:35:50 -04:00
metatroncubeswdev
ce75d45141 Phase 4: activity log — who did what in the workspace
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
- activity_log table (sqlite + pg, structurally identical; schema-parity
  covers it). Plain-text columns, no FKs — an append-only trail that must
  outlive the projects/users it references, so target_label snapshots a
  human-readable name at write time.
- ActivityRepository: record() (fire-and-forget, never breaks the caller) +
  list() (org-scoped, actor/action filters, keyset pagination) + listActors().
- Recording wired into the mutations worth tracking: project
  create/archive/restore/domain, audit start, team user create/remove/
  password-reset, invitation sent.
- getActivityLog / getActivityActors server functions (owner/admin gated) +
  Settings → Activity tab (ActivityLogView: filter by user & action, load
  more).
- Migration: drizzle/0045_*, drizzle-pg/0023_*. The pipeline does not run
  migrations — see docs/SELF_HOSTING_TEAM_MODE.md step 5 for the one-time
  `drizzle-kit migrate` on the server. Writes fail silently until the table
  exists.

tsc / oxlint / knip clean. New ActivityRepository.test.ts (4) + schema-parity
picks up the new table; suite otherwise unchanged (pre-existing samSkills
CRLF failure only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 16:00:09 -04:00
metatroncubeswdev
29bda614a4 Fix team-mode first-run: /setup no longer bounces to /sign-in
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
- _auth.setup.tsx: the "owner already exists?" check ran in beforeLoad, which
  executes during SSR where fetchTeamSetupStatus's relative fetch to
  /api/team-setup fails — so it always concluded an owner existed and
  redirected to /sign-in, making the create-owner screen unreachable. Move the
  check into a client-side effect with a loading state.
- setup-status.ts: add BETTER_AUTH_URL to CHECK_ENV_VARS so /api/health stops
  falsely reporting "team mode requires BETTER_AUTH_URL" when it is set (the
  Docker preflight already saw it; only the runtime health check's env
  allowlist was missing it).

Verified locally end to end against a D1 build in AUTH_MODE=team: owner
bootstrap, self-disable + 409 on repeat, Better Auth sign-in issues a session
cookie, and get-session resolves the shared organization.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 14:19:28 -04:00
metatroncubeswdev
acc35c055c Phase 3: team-mode owner setup, user management, shared workspace
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Makes AUTH_MODE=team usable end to end.

- resolveTeamContext (middleware/ensure-user/team.ts): a session resolves to a
  membership in the single shared workspace. No per-user fallback org — a
  signed-in user with no membership is treated as signed out, so the owner can
  actually remove people.
- teamProvisioning.ts: one path that writes user + credential account + member
  together (hashPassword from better-auth/crypto). Shared by both entry points.
- /api/team-setup (raw route, outside auth middleware): GET reports whether an
  owner is needed; POST creates the first owner + the shared org, then
  self-disables once any user exists.
- /setup route + sign-in redirect: first run sends you to create the owner.
- teamUsers server functions (owner/admin-gated): list / create (with temp
  password) / reset password / remove. Removal drops membership + sessions,
  keeps the user row for historical attribution.
- Settings gains a "Users" tab in team mode (TeamUsers.tsx).
- docs/SELF_HOSTING_TEAM_MODE.md: activation runbook (.env, build, first owner).

No DB migration — all rows are existing better-auth tables. tsc / oxlint / knip
clean. New teamProvisioning.test.ts (4 cases) passes; suite otherwise unchanged
(pre-existing samSkills.test.ts CRLF failure only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 08:13:01 -04:00
metatroncubeswdev
c47b032f1a Add team auth mode (backend, inert until AUTH_MODE=team)
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
Introduces a fourth AUTH_MODE, `team`: Better Auth email/password with the
existing organization/member/role/invitation stack, but none of the hosted
SaaS coupling (no Autumn billing, Turnstile, Loops email, Google social
login, onboarding chat, PostHog, disposable-email block, dub referrals).

- auth-mode.ts: add `team`; add isTeamAuthMode / isSessionAuthMode /
  isSessionClientAuthMode ("is there a login session?" vs isHostedAuthMode's
  "is this the billed product?").
- auth.ts: createAuth() builds a valid instance for `team` — verification
  off, self-serve signup disabled, no captcha/Loops/social. hasTeamAuthConfig
  (BETTER_AUTH_URL + BETTER_AUTH_SECRET only) + hasSessionAuthConfig.
- ensure-user: resolve.ts routes `team` through resolveHostedContext;
  requireHostedSession + selfHostedOAuth callback accept any session mode.
- api/auth/$.ts: mount the Better Auth handler for `team` too.
- Client: route guards, sidebar account menu / sign-out, settings
  Organization tab, invitation accept, and error cards switch from
  isHostedClientAuthMode to isSessionClientAuthMode where they mean "has a
  session". Sign-in goes straight to the email form (no Google button);
  sign-up shows an invite-only notice.
- selfhost-preflight: validate `team` (requires BETTER_AUTH_URL +
  BETTER_AUTH_SECRET >= 32 chars).
- .env.example: document `team`.

Ships inert: AUTH_MODE stays local_noauth. tsc / oxlint / knip clean;
test suite unchanged (1164 pass, 1 pre-existing Windows-CRLF failure in
samSkills.test.ts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 00:51:20 -04:00
metatroncubeswdev
b489f78129 Rebrand app to CrawlerX / MetatronCube theme
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
- DaisyUI themes openseo/openseo-dark -> crawlerx/crawlerx-dark on the
  MetatronCube palette (primary #3779b9, secondary #0f1d34, accent #4faede)
- Load Inter as the app font; add --brand-gradient / .brand-gradient
- Cube mark + "CrawlerX" wordmark in the sidebar and mobile top bar
- Add public/crawlerx-mark.png; point transparent-logo.png at the cube mark
- <title>, site.webmanifest, and all user-facing "OpenSEO" copy across
  src/client and src/routes -> "CrawlerX"

Deferred: favicons (need resizing), agent-facing identity (MCP server
name, SAM/onboarding prompts, fact sheet), web/ marketing site.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 00:00:27 -04:00
ea8becd433 Update compose.yaml
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
2026-09-08 21:20:39 +00:00
Developer
aefbf86e08 Migrate project to Gitea
Some checks failed
CI / ci (push) Has been cancelled
CI / docker-build (push) Has been cancelled
Publish Docker image / docker (push) Has been cancelled
Upload sourcemaps / upload (push) Has been cancelled
2026-09-08 21:08:29 +00:00
Jeremy Rivera
3632f40852
Blog: What Broke the $99 Ceiling (#277) 2026-09-03 11:54:34 -04:00
Jeremy Rivera
5b242b225a
Blog: Two Surfaces, Two Timelines (#278) 2026-09-03 11:54:23 -04:00
Ben Senescu
ac9ee482d2
Revert "fix(audit): back off and retry on 429 instead of recording the page a…" (#564)
This reverts commit bb099ad65ae9ac50a6d900c5f61bd0a942661333.
2026-08-28 16:16:44 -04:00
Ben Senescu
ad2d28ea6f
fix(ga4): honor full date ranges instead of clamping to 90 days (#563) 2026-08-28 16:15:22 -04:00
Ben Senescu
bb099ad65a
fix(audit): back off and retry on 429 instead of recording the page as blocked (#562) 2026-08-28 15:27:23 -04:00
Ben Senescu
accac73e16
feat(billing): collect business name, address, and tax ID at checkout (#558) 2026-08-27 18:56:26 -04:00
Ben Senescu
b0248f2acd
release: v0.1.7 (#554) 2026-08-27 18:31:03 -04:00
Ben Senescu
749b38118d
fix: show GA4 MCP rows in Claude text output (#553) 2026-08-27 18:02:13 -04:00
Ben Senescu
ea162a4391
feat(orgs): multi-user workspaces — roles, invitations, membership enforcement (#473) 2026-08-26 16:54:08 -04:00
Ben Senescu
4d7fb661f0
Switch chat agents to GPT-5.6 Luna (max reasoning) (#499) 2026-08-26 16:39:51 -04:00
Ben Senescu
61b32ec647
fix: extend OAuth state cookie lifetime to match the 10-minute state TTL (#544) 2026-08-26 14:37:46 -04:00
Ben Senescu
b32c0bd841
fix: surface Google connect failures to the user instead of dead-ending (#549) 2026-08-26 13:23:20 -04:00
Ben Senescu
9b12e073a8
fix: replace the broken per-key API rate limit with a real 5000/min per-user /mcp limit (#545) 2026-08-26 12:09:31 -04:00
Ben Senescu
f35bbb8753
chore: add internal observability-triage skill (query recipes + known-noise filters) (#540) 2026-08-26 12:08:50 -04:00
Ben Senescu
11a874ed3b
chore: log Lighthouse runtime errors at warn and include strategy (#539) 2026-08-26 11:51:59 -04:00
Ben Senescu
c7ff28c30a
chore: log rank-check live call failures with error code and keyword, warn on upstream flakes (#542) 2026-08-26 11:51:26 -04:00
Ben Senescu
824e914eb1
fix(mcp): refuse subscriptions/listen streams — MCP serving is stateless (EVE-95) (#548) 2026-08-26 11:48:20 -04:00
Ben Senescu
0abde80109
fix: add 10s timeout to Loops fetches (#543) 2026-08-26 11:41:22 -04:00
Ben Senescu
95551a425a
chore: log expected credit refusals in backlink snapshot refresh at info (#541) 2026-08-26 11:39:50 -04:00
Ben Senescu
7918fdb8c7
fix: remove duplicate retry:false in useKeywordSerpAnalysis query options (#547) 2026-08-26 11:34:57 -04:00