fix(admin): auto-approve member logo uploads that pass format/size/safety checks#3393
Conversation
|
TypeScript Build is failing — need to investigate which test imports member-context or auth chain that's now broken. Common pattern: lazy-import the problematic dependency, or add proper vi.mock() for auth/workos in the failing test. Reference: PR #3258's lazy-import fix. |
|
Fixed in 634ff75.
Applied the same lazy-import fix: removed the top-level import and replaced both call sites (lines 7672 and 7784) with Generated by Claude Code |
|
Acknowledged — lazy-import fix in 634ff75 looks correct, same pattern as the #3258 fix in Generated by Claude Code |
|
Routine: this PR is DIRTY against main. Please rebase against |
|
Routine: persistently DIRTY against main as other PRs land. Please rebase locally against |
…fety checks Closes #2568. Mary launch blocker — logos uploaded by members sit in a pending queue with no admin UI and no member-visible resolution path. - brand-logos.ts: community uploads now auto-approve (review_status: 'approved') after passing the existing membership + ban + magic-bytes + SVG-sanitization + size gates. Manifest rebuild extended to all uploads (was owner-only). Source still tracks brand_owner vs community. - brand-viewer.html: success message now reflects actual review_status from the API response ('Logo uploaded and live.' vs 'pending review.') instead of hardcoding the pending message. - brand-tools.ts: Addie upload_brand_logo tool had the same pending-only logic as a separate code path. Fixed to match HTTP route: inserts as approved, rebuilds manifest, returns correct status. - brand-logo-db.ts: insertBrandLogo default changed from 'pending' to 'approved' so future callers that omit review_status don't silently re-introduce the queue. - brand-logo-digest.ts: comment updated to explain the job is now a drain for pre-deploy historical pending logos only. - changeset auto-approve-verified-owner-logos.md: removed now-incorrect note that community uploads still queue. https://claude.ai/code/session_019WyF5yW7B8jkypARtKHqcg
Top-level import of member-context.ts transitively loads middleware/auth.ts, which constructs a WorkOS client at module load time. Any test that imports admin-tools.ts without WORKOS_API_KEY set (or without mocking middleware/auth) fails with a WorkOS constructor error. Matches PR #3258's fix for the same pattern in member-tools.ts: remove the top-level import and use `await import('../member-context.js')` inside the two handlers that call invalidateMemberContextCache(). https://claude.ai/code/session_01J5x2do9fKEfGg3uZGZtAzw
634ff75 to
b0e2ece
Compare
|
Rebased against One modify/delete conflict on Generated by Claude Code |
|
Got it — rebase noted, conflict resolved cleanly, Generated by Claude Code |
|
Acknowledged — glad the rebase carried through cleanly. No action needed on my end. Generated by Claude Code |
|
Noted, thanks for confirming. No further action from this end. Generated by Claude Code Generated by Claude Code |
|
Acknowledged — standing by if anything else comes up. Generated by Claude Code Generated by Claude Code |
… to verified owners (#4743) * fix(brand-viewer): restore community brand serving + lock logo writes to verified owners Issue A — /brands/{domain}/brand.json silently started 404ing for hand-curated rows after #3529. Two root causes: - editDiscoveredBrand never promoted source_type when a human edited, so Brandfetch-seeded rows that AAO members curated (scope3.com, fandom.com) stayed source_type='enriched' and tripped the new gate. - The structural-shape check in #3529 demanded house/brands/agents/ brand_agent/authoritative_location at the manifest root; the AAO edit UI writes flat manifests that don't fit any of those shapes. Fix: drop the structural-shape check (the source_type gate alone keeps raw Brandfetch data out); promote enriched→community in editDiscoveredBrand; one-shot migration backfills any enriched row that already has revisions (= a human curated it). Issue B — logo uploads auto-approved instantly for any AAO member, including on brands they don't own (#3393). Brian's call: if a brand has a verified owner, only that org can write. Implemented: - Verified owner exists + caller is org member → 201 approved - Verified owner exists + caller is not in org → 403 verified_owner_required - No verified owner → community uploads queue as pending review Walks back the community half of #3393's auto-approval. Moderation queue throughput is an ops problem. 24 unit tests across 3 new files cover the brand.json gate, source_type promotion (enriched promotes, community doesn't churn, brand_json still rejected), and the full upload auth matrix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(test): drop unused PNG_HEADER constant flagged by code-quality bot Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(brand-viewer): address expert-review feedback Defense-in-depth from security + code review of #4743: - Lock Addie's upload_brand_logo MCP tool to the same write-authority gate as the HTTP route. Previously the tool hardcoded review_status='approved' and bypassed the verified-owner check, making it a parallel door past the route-level fix. Now refuses on verified-owned brands and queues as 'pending' otherwise. - Restrict enriched→community promotion in editDiscoveredBrand to actual brand-content changes from non-system editors. Previously, any edit call promoted enriched rows — including the audit-only revision the logo-upload route writes (no manifest input) and the manifest-rebuild call the logo-service makes after approval (system caller, just refreshes the logos array). Either path was a stealth route to publish raw Brandfetch data under the community label. - Mirror the rule in migration 483: only backfill enriched rows whose brand_revisions contain at least one non-system-attributed entry. Logo-upload manifest-rebuild revisions (system:logo-service) no longer trigger retroactive promotion. - Improve 403 copy on verified_owner_required: include a claim_url pointing at /brand/builder?domain=... so rejected users know how to prove ownership instead of giving up. - Add a "queued for moderator review" message to community-upload 201 responses so the uploader knows their change isn't live yet. - Replace empty catch around the audit revision write with a logger.debug call. 41 unit tests across 4 files pass (incl. new addie-upload-brand-logo-auth suite). Typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes #2568
Member logos uploaded during onboarding sit in a
pendingreview queue indefinitely — no admin UI exists to process it, the only consumer is an Addie MCP tool (list_pending_brand_logos) most admins don't know to invoke, and members see a hardcoded "pending review" message with no resolution path. This is the escalation source identified in the Apr 11–18 Addie insights.This PR removes the bottleneck by auto-approving all uploads that already pass the membership + ban + magic-bytes + SVG-sanitization + size gates. Source traceability (
brand_ownervscommunity) is preserved. The reject/delete admin path is unchanged. Theupload_brand_logoAddie tool was a separate code path with the same hardcodedpendinglogic — it's fixed in the same diff.Non-breaking justification: No schema or wire changes.
review_statuswas already returned in the HTTP upload response; callers that read it now see'approved'instead of'pending'. No existing client depends on community uploads being held in pending state.Files changed:
server/src/routes/brand-logos.ts—reviewStatusalways'approved'; manifest rebuild unconditional; edit summary records sourceserver/public/brand-viewer.html— success message usesresult.review_statusfrom API responseserver/src/addie/mcp/brand-tools.ts—upload_brand_logotool: insertapproved, callrebuildManifestLogos, return correct status; description updatedserver/src/db/brand-logo-db.ts—insertBrandLogodefault changed from'pending'to'approved'(latent footgun fix)server/src/addie/jobs/brand-logo-digest.ts— comment updated: job is now a drain for pre-deploy pending logos only.changeset/auto-approve-verified-owner-logos.md— removed contradicting note that community uploads still queueNits surfaced in review (not fixed here):
countBrandLogosandgetByDomainAndSha256still referenceIN ('pending', 'approved')— functionally fine, cosmetic cleanup follow-uprebuildManifestLogos+editDiscoveredBrandare two sequential writes to the same brand row per request with no transaction wrap — pre-existing race under concurrent same-domain uploads; tracked separatelyPre-PR review:
rebuildManifestLogosplacement correct in both code pathsisOwneris still needed forsourcefield and audit summary so the call is not deadSession: https://claude.ai/code/session_019WyF5yW7B8jkypARtKHqcg
Generated by Claude Code