Skip to main content

Platform-specific features (the full diff)

Related pages. The three-layer stack is the summarised positioning; this page is the full feature-by-feature enumeration. Honest comparisons ยง vs vanilla Label Studio is the same content shaped for the competitive question.

What this platform adds vs upstream Label Studio

AfriAnnotate is a fork of Label Studio. The labelling editor, the XML tag library, the core API contract, and most annotator-facing UI inherit from upstream. But many features that upstream gates behind their commercial Enterprise edition (or doesn't ship at all) are built natively in AfriAnnotate. This page is the diff โ€” useful for:

  • Migrating from upstream Label Studio (what would you gain?)
  • Evaluating the fork (what's the actual value-add?)
  • Contributing back (these are the candidate features to upstream)

Core platform additionsโ€‹

These are the structural features upstream LS open-source ships as stubs or doesn't ship at all โ€” built natively in AfriAnnotate.

Real RBAC + role permission matrixโ€‹

Upstream Label Studio defines 30+ permission names but every one resolves to is_authenticated โ€” there's no actual role logic in the open-source edition.

AfriAnnotate ships a full six-role permission matrix:

  • Owner (OW) โ€” top org role; can do anything
  • Admin (AD) โ€” manage members + projects, can't transfer ownership
  • Manager (MA) โ€” create + edit projects, manage project members
  • Reviewer (RE) โ€” review annotations, can label too
  • Annotator (AN) โ€” label tasks they're assigned to
  • Guest (GU) โ€” read-only observer for stakeholders / auditors / new hires shadowing

Plus per-project role overrides (an org-level Admin can be just an Annotator on a specific project). Plus the is_staff / is_superuser platform-level flags layered on top.

Enforcement is at the queryset layer in DRF permission classes โ€” not just URL gating. See Roles for the full matrix.

Multi-organisationโ€‹

Upstream LS open-source auto-creates one organisation on signup with the create-org endpoint hidden + no UI. Effectively single-tenant.

AfriAnnotate ships full multi-org:

  • Users belong to N orgs simultaneously, switch between them via the sidebar
  • Each org has its own member list, projects, branding, settings, consent library
  • Cross-org access is impossible โ€” every database row carries an organization FK and is filtered at the queryset level
  • Platform staff can create / delete / freeze orgs from the Platform dashboard (Platform โ†’ Orgs)

Multi-tenancy + row-level isolationโ€‹

Beyond just having multiple orgs, every database row carries the org FK and every query in DRF is filtered by the requesting user's active org. There's no path by which a user in org A can see rows from org B by guessing IDs โ€” the check is at the data layer, not the URL layer.

Documented in Security model โ†’ Multi-tenancy.

Review / QA workflowโ€‹

Upstream open-source LS has no reviewer role and no approve/reject state on annotations. The data model has hooks but no flow.

AfriAnnotate ships a full review workflow:

  • Reviewer role with its own permissions
  • Per-task reviewer assignment + reviewer-stream queue
  • Accept / Reject / Fix-and-accept decisions
  • Reject reason (optional comment required policy)
  • Tie-breaker-only mode (only surface disagreed tasks)
  • Cross-project review queue at the org level
  • Annotation locks post-submit + post-acceptance

See Review workflow and Review settings.

Audit log (append-only)โ€‹

Upstream open-source LS has no audit log. AfriAnnotate ships:

  • AuditEvent model that records every staff action + sensitive user action (signup, login, role change, project create / delete, consent sign / revoke, token create / revoke, etc.)
  • Append-only at the DB layer โ€” on PostgreSQL a row-level trigger refuses every DELETE and every UPDATE (the only change it lets through is the ON DELETE SET NULL cascade when a user or organisation is deleted; the snapshotted actor email keeps the row meaningful). Covered by tests; see Security model โ†’ Audit log
  • Combined with the consent module's hash chain, the audit surface is tamper-evident
  • Filterable + exportable from Platform โ†’ Audit log

Transactional email + verificationโ€‹

Upstream open-source LS has an email stub โ€” a Django backend class exists but no templates, no sending, no DNS guidance.

AfriAnnotate ships:

  • Full transactional email via any SMTP provider (Brevo / SendGrid / SES / Mailgun / Postmark โ€” see Email delivery)
  • Per-event templates managed at Platform โ†’ Notifications with {{verify_url}} / {{display_name}} / {{platform_name}} substitution
  • Email verification gate โ€” required before sign-in for all non-first users; one-shot tokens with 24h TTL
  • Email change flow with re-verification on the new address
  • Manual-verify escape hatch for corporate-filter-blocked users (Mark a user verified)

In-app + email notificationsโ€‹

Upstream open-source LS has no notification system. AfriAnnotate ships:

  • In-app notification center (bell icon in the top-right)
  • Per-event toggles for what surfaces (consent revoked, annotation rejected, review queue grew, quota threshold crossed, auto-suspend triggered, etc.)
  • Email digest option for users who'd rather batch
  • Per-user overrides in Profile โ†’ Preferences (email digest cadence + email volume) that layer on top of the platform defaults

Branding (no-rebuild rename)โ€‹

Upstream open-source LS hardcodes "Label Studio" in many places โ€” rebranding requires recompiling.

AfriAnnotate ships runtime branding:

  • Platform name + logo + favicon + From email all configured at Platform โ†’ Settings โ†’ Branding โ€” no rebuild required
  • Propagates to browser title, login page, email subjects, mobile splash, in-app copy
  • The docs site itself is rebrand-configurable via a single config file (docs-site/branding.config.js) โ€” see Hosting runbook

Rate-limit tunabilityโ€‹

Upstream LS has hardcoded rate limits in middleware. AfriAnnotate ships operator-tunable rate limits stored in PlatformSettings:

  • Per-endpoint base + cap for the (IP, email) exponential backoff
  • Tune up for high-traffic deployments
  • Tune down for internal-only platforms
  • Changes take effect immediately โ€” no deploy

Labelling tags (new XML tags)โ€‹

Five new tags in the XML library, all marked with the platform-name badge in the Tag reference:

  • <AudioRecord> โ€” in-browser audio capture for ASR / TTS corpus collection. WebM/Opus default, configurable bitrate / sample rate / noise cancellation, optional live waveform + server-side QC checks.
  • <AudioTextAlign> โ€” pair audio with transcript and align words / tokens to time positions. Word vs phoneme granularity, token vs span mode, optional autoalign via Whisper / MMS. Now supports tier hierarchies (tiers="utterance,word:utterance:subdivision") and .eaf import, giving the field-linguistic tier model that field linguists otherwise reach for a desktop tier editor for โ€” inside a multi-user platform.
  • <KBRef> โ€” attach a concept from a curated Knowledge Base to a region (Phase 3.1). Autocomplete against label / aliases / external_id. The standard entity-linking layer above NER; the annotation stores the concept's external_id + label for downstream normalisation.
  • <TypedFeature> โ€” attach a form of dtype'd attributes (string / boolean / integer / float / link / concept_kb_ref) to a region, with feature defs managed at Project โ†’ Settings โ†’ Typed layers (Phase 3.1). The INCEpTION pattern generalised: NER + KB link + per-span structured metadata all on one canvas without a proprietary XML schema.
  • <MultiModalCanvas> โ€” binds several time-based object tags (Audio, Video, AudioTextAlign, TimeSeries, AudioRecord) into ONE labeling surface with ONE playhead and ONE shared-region timeline (Phase 3.3). Regions drawn on the shared strip apply across every modality. The "one recording, many views" pattern common in speech, gesture, and audio-video corpus annotation.

Semantic + knowledge-base annotation (Phase 3.1)โ€‹

Named Entity Linking + typed-attribute annotation are first-class, not add-ons.

  • KnowledgeBase model at the org level โ€” local (managed in-platform), remote (external autocomplete endpoint), or Wikidata backends. Entries carry external_id, label, aliases, description; TSV/CSV bulk import; CRUD APIs.
  • TypedFeatureLayer at the project level โ€” named layer with kind (span / relation / chain / document) and a set of typed features. Each feature has a dtype: string, boolean, integer, float, link, or concept_kb_ref.
  • <KBRef> control tag renders KB autocomplete tied to a region; <TypedFeature> renders the appropriate dtype-per-feature form (text / checkbox / number / URL / embedded KB search) on the same region.
  • Named Entity Linking (KB-backed) template ships in the project- creation Labeling Interface picker โ€” instantiates <Labels>, <Text>, <KBRef>, and <TypedFeature> together with the setup steps walked through in the template's details panel.

Reach for INCEpTION when the formal typed-layer constraint system (alignable-vs-referring tiers, cascading cross-layer references) is the point of the project. AfriAnnotate covers the everyday NEL + typed-attribute pattern inside a multi-modal team platform.

Multi-modal shared canvas (Phase 3.3)โ€‹

<MultiModalCanvas> binds several time-based object tags into ONE labelling surface. The canvas acts as the "conductor" of a sync group โ€” its sync= attribute names the group, and every child tag with the same sync= value participates. Play/pause on any child drives all; regions drawn on the shared strip apply across every modality; per-tag regions (Audio waveform selections, Video bounding boxes) still work orthogonally.

Payoff for the "one recording, many views" pattern common in speech, gesture, and audio-video corpus annotation โ€” audio + video of a lecture, a signed conversation with gloss transcript, an interview with speaker-diarised audio all annotated in one task without switching context.

Per-project featuresโ€‹

Audio QCโ€‹

Audio QC โ€” server-side automated quality checks for audio recordings. Three tiers: cheap default-on (duration, peak, clipping, loudness LUFS, SNR, speech ratio, silence), heavy opt-in (Whisper transcript match, MMS forced alignment, DNSMOS / NISQA MOS, speaker consistency), and hard- reject corruption-level. Action on fail (warn / route to review / re-record / block). In-process or external MLBackend dispatch.

Licensing decision treeโ€‹

Licensing โ€” guided 5โ€“8 question wizard that maps to nine SPDX outcomes (CC0, CC-BY, CC-BY-SA, CC-BY-ND, CC-BY-NC, CC-BY-NC-SA, CC-BY-NC-ND, Proprietary, Restricted). Persists the reasoning trail for dataset-provenance auditing. Surfaces in project header + export manifest.

Data securityโ€‹

Per-project data security โ€” four templates (Basic / Compliance-Strict / Operational-Permissive / Custom). Toggles for offline allowed / metadata mirror / multi-device / multi-user-per-device / browser caching / cache wipe on logout / fresh session for export / annotator-action audit logging / lock-after-submit / restrict-export-to-managers / max offline cache age. Distinct from upstream's coarse-grained permissions.

Annotation behaviour extrasโ€‹

Beyond upstream's max-annotations-per-task setting:

  • Per-annotator annotation limit โ€” per-person cap on how much one annotator can claim (Settings โ†’ Quality โ†’ Annotation Limit)
  • Annotations per task โ€” structural constraint (e.g. "โ‰ฅ 1 aspect" for ABSA, "exactly 1 span" for QA)
  • Annotator-facing language โ€” the labelling stream renders in a project-specific language regardless of the annotator's profile preference (Settings โ†’ General)

Per-organisation featuresโ€‹

Consent library โ€” versioned consent templates with per-purpose granular consent (GDPR Article 7 compliant), typed signatures, age attestation, country-of- residence capture, HMAC-SHA256 hash-chain audit log. Eight kinds of consent (data use, NDA, ethics, voice release, etc.).

Auto-suspend rulesโ€‹

Auto-suspend โ€” automatically pause org members based on 7 rule types (inactivity, low agreement, high rejection rate, low throughput, high abandonment, quota exceeded, custom Python metric). Grace-period warnings, per-rule scope, three unsuspend paths.

Metrics dashboardsโ€‹

Org + project metrics โ€” six org panels (overview, timeseries, contributors, activity, evaluations, label distribution) + four project panels (overview, timeseries, annotators, agreement). Full REST API. Pretty heavy compared to upstream's annotation-counts.

Member suspension + invite policiesโ€‹

Suspend + invite policies โ€” suspension without removal (preserves audit trail), default-role- on-invite, email-domain allowlist on invites.

Per-annotator quality featuresโ€‹

Annotator evaluation โ€” three related per-person quality gates:

  • Calibration ramp โ€” new annotators warm up on ground-truth tasks before live data
  • Min-score pause โ€” rolling agreement below threshold = auto- pause (project-level)
  • Low-agreement auto-routing โ€” disputed tasks auto-pushed to review or re-annotated

Plus a custom agreement metric sandbox (Python) and an embedding-API config for semantic-similarity scoring.

Per-platform featuresโ€‹

Quotasโ€‹

Org quotas โ€” per-org caps on max members / max projects / max tasks. Enforcement at mutation points, 80% / 100% threshold notifications, bulk-increase API for billing- system integration.

Branding + rate limitsโ€‹

Platform Settings โ€” platform name + logo

  • from-email at runtime (no rebuild), per-endpoint rate limits tunable without deploy.

Audit log with append-only DB triggerโ€‹

Platform audit log โ€” append-only at the DB layer (a PostgreSQL trigger refuses UPDATE and DELETE), combined with the consent module's hash chain for a tamper-evident compliance trail.

Session timeout policy (per-org)โ€‹

Session policy โ€” per-org max session age + max time between activity. Different orgs on the same platform can have different security postures.

Desktop + mobile distributionโ€‹

Mobileโ€‹

Mobile install โ€” Capacitor-based thin- client app distributed via Firebase App Distribution (Android) and TestFlight (iOS). Same SPA, native shell. Architecture documented at Mobile architecture.

Desktopโ€‹

macOS desktop โ€” Tauri-based wrapper, distributed as a notarized .dmg outside the Mac App Store. Less friction than TestFlight macOS for embedded- runtime apps.

Offline sync (production-hardened, Phase 4)โ€‹

Offline sync โ€” desktop app's SQLite mirror + bidirectional sync (afri_sync module). SyncMeta shadow table for dirty-tracking, CloudProxyMiddleware for transparent local-vs-cloud routing, conflict resolution.

Phase 4 productionised the mobile / browser side:

  • Write-through IndexedDB cache for tasks, projects, annotations, and drafts. Reads go local-first; writes hit both the local cache and the outbox in one atomic step.
  • Resumable offline download โ€” per-project checkpoint that survives cancel or crash. If a 4,000-task project download aborts at task 2,873, the next resume picks up exactly there. A Cancel button on the download UI runs a partial-cache-preserving abort path, so cancelling doesn't nuke the tasks already stored.
  • Outbox backoff + idempotency โ€” every pending mutation gets a client-side unique_id; when the server hits an existing one it short-circuits with 200 OK instead of duplicating. Exponential backoff, Retry-After header respected, capped max delay. No double-writes on flaky links.
  • Pointer-events touch parity on Audio waveforms, Video canvases, Image / Video / TimeSeries drag runners โ€” annotators on tablet / touch-first screens draw regions, drag playheads, and resize boxes with the same fidelity as mouse users.
  • Mobile side-panels default collapsed on narrow viewports so the labelling canvas gets the screen real estate it needs.

Operator + admin toolsโ€‹

Management commands โ€” CLI commands for housekeeping: run_auto_suspend_rules, backfill_agreement, detect_label_drift, expire_pending_invites, send_inactivity_reminders, calculate_stats, afri_sync_pull. All operator-runnable; most wire into Cloud Run jobs or cron.

Operator FAQ โ€” hoster-facing troubleshooting for cloud-deploy issues, email deliverability, build-pipeline gotchas, database scale guidance, self-hosting alternatives (AWS mapping, single-VPS minimal viable).

Distribution scaffoldingโ€‹

End-to-end build + ship scripts for all four artifacts:

Plus the hoster setup runbook tying them together.

Docs site itselfโ€‹

The fact that the docs site rebrands cleanly via a single config file (docs-site/branding.config.js) is itself AfriAnnotate-specific. Every page on the site uses AfriAnnotate / https://afriannotate.waraka.org / https://github.com/warakacommunity/afriannotate / afriannotate.waraka.org / no-reply@label.afriannotate.org etc. โ€” substituted at build time by a remark plugin. Fork the repo, edit one file, rebuild โ€” the docs come out branded for your hoster.

Things we did NOT changeโ€‹

For context, here's what stayed identical to upstream Label Studio:

  • The XML tag library โ€” upstream apart from our additions: <AudioRecord>, <AudioTextAlign>, <VideoRecord>, <VideoTiers>, <MultiModalCanvas>, <KBRef>, <TypedFeature>
  • The labelling editor (LSF) โ€” the embedded React widget that renders inside the browser
  • The REST API for tasks / annotations / projects (we added new endpoints under /api/afri/, /api/consent/, /api/audio-qc/, etc., but didn't break upstream paths)
  • The XML labelling-config grammar (our tags inherit the same parser)
  • The basic project / task / annotation data model (we added new fields like audio_qc_*, license, allow_offline_*, but didn't remove or rename existing ones)

The upstream Label Studio team's work is the foundation; this list is the diff.

Reading furtherโ€‹