dFeature/zentropi signal integration (#42)
* Add ZENTROPI integration and ZENTROPI_LABELER signal type enums
Add Zentropi as a new third-party integration and ZENTROPI_LABELER as
a new signal type across TypeScript enums, GraphQL schema, and
generated types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add Zentropi credential storage and database migration
Add ZentropiCredential type, CRUD operations for per-org API key
storage, and migration to create signal_auth_service.zentropi_configs
table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add Zentropi signal implementation
Implement ZentropiLabelerSignal and zentropiUtils following the OpenAI
Moderation pattern. Calls POST /v1/label with policy-steerable labeler,
maps label+confidence to a composite 0-1 score, and handles permanent
errors (401/404) vs transient errors (5xx).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Wire up Zentropi signal with cached fetcher and credential getter
Register ZentropiLabelerSignal in instantiateBuiltInSignals, add
cached Zentropi API fetcher (with labeler-aware cache keys), and
add cached credential getter for ZENTROPI integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add tests for Zentropi signal integration
Test score mapping (all four quadrants), signal class metadata,
disabled info, error handling (401/404 permanent, 5xx transient,
missing subcategory), and correct API call parameters.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix Zentropi label type coercion and test credential helper
The Zentropi API returns label as a string ("0"/"1") rather than a
number. The strict equality check (label === 1) would always fail,
causing violating content to receive a safe score. Use Number(label)
to handle both string and number responses.
Also fix test helper makeCredentialGetter to use string | null instead
of string | undefined, since passing undefined explicitly triggers the
JS default parameter value, making the missing-credentials test path
ineffective.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add labeler version IDs to Zentropi integration
Store labeler versions (id + label pairs) in the Zentropi integration config
alongside the API key. The eligibleSubcategories resolver dynamically returns
org-specific labeler versions, and the subcategory picker renders a dropdown
for flat subcategory lists. Also fixes spot test to work on rules regardless
of their enabled status.
* Address PR review feedback: add missing DB enum, use fetchHTTP, bind in cached fetchers
- Add ZENTROPI_LABELER to enum_signals_type in migration SQL
- Replace raw fetch() with shared fetchHTTP dependency in getZentropiScores
- Bind fetchHTTP into getZentropiScores in makeCachedFetchers
- Update tests to mock fetchHTTP instead of global.fetch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Inline override values in ZentropiLabelerSignal, remove wrapper functions
Move simple return values (docsUrl, integration, pricingStructure, etc.)
directly into the signal class instead of delegating to single-use
functions in zentropiUtils.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Collapse Zentropi migrations into a single file
Merge labeler_versions column into the initial CREATE TABLE instead of
a separate ALTER TABLE migration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix lint and betterer CI failures
Use Object.assign instead of property mutation in test helpers to
satisfy better-mutation/no-mutation rule. Replace @ant-design/icons
with lucide-react equivalents in IntegrationConfigApiCredentialsSection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix remaining lint errors in spotTest and signalAuthService
Remove unnecessary null check in spotTest (getGraphQLRuleFromId always
returns or throws). Replace JSON.parse/JSON.stringify with jsonParse/
jsonStringify in signalAuthService per codebase conventions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bump zentropi migration datestamp to avoid ordering conflict
Main already has a migration at 2026.02.10T00.00.00; rename ours
to 2026.02.18T00.00.00 so it runs after all existing migrations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: samidh <Samidh@host4-129-30-192.springshosting.net>
This is a binary file and will not be displayed.