Docs / Cross-SDK Parity

Cross-SDK Parity

Same input gets the same answer in Node, Python, and Go. Enforced by a shared specification, shared test vectors, and a runtime conformance harness. This page shows you the contract.

The contract

Every public function in Arcis is governed by three files in the repo:

  1. spec/API_SPEC.md — function signatures, parameter names per language convention, defaults, return shape
  2. spec/TEST_VECTORS.json — input strings and expected behavior every SDK must produce identically
  3. packages/core/patterns.json — the regex corpus loaded by every SDK at runtime (Node from source, Python from source, Go via //go:embed)

A change that breaks parity fails CI loud. A pattern added to one SDK but not the other two cannot be merged.

Example: XSS sanitization

The same payload through the same call across three runtimes:

Input

"<script>alert(1)</script>Hello"

Node

import { sanitizeString } from '@arcis/node';

sanitizeString('<script>alert(1)</script>Hello');
// => "Hello"

Python

from arcis import sanitize_string

sanitize_string('<script>alert(1)</script>Hello')
# => "Hello"

Go

import "github.com/GagancM/arcis/sanitizers"

sanitizers.SanitizeString("<script>alert(1)</script>Hello")
// => "Hello"

Example: NFKC + multi-decode

A v1.6 bypass-resistance case. Fullwidth + URL-encoded variants reach the detector as the same string in all three SDKs.

Input

"%EF%BC%9Cscript%EF%BC%9Ealert(1)%EF%BC%9C/script%EF%BC%9E"
// percent-encoded form of fullwidth <script>alert(1)</script>

After NFKC normalization the fullwidth glyphs collapse to ASCII < >. After the multi-decode chain the percent-encoded form decodes. The XSS pattern matches. All three SDKs return:

// => "alert(1)"

(Or the empty string, depending on whether sanitization or detect-then-block was wired up. Either way, identical across SDKs.)

Conformance harness

A Python script at documents/attacks/cross_sdk_conformance.py runs 26 representative inputs through both arcis.sanitize_string (Python) and sanitizeString (Node, via a child process), and asserts byte-identical output.

$ python documents/attacks/cross_sdk_conformance.py
loaded 26 test vectors from spec/TEST_VECTORS.json
running Python sanitize_string...
  26 outputs
running Node sanitizeString...
  26 outputs

OK: Python and Node produce identical output for all 26 test vectors.

The harness ran during every Arcis dev session in v1.5 and v1.6. The TEST_VECTORS.json grows as new vectors land.

Naming conventions

Same semantics, language-idiomatic names:

ConceptNodePythonGo
Sanitize stringsanitizeStringsanitize_stringSanitizeString
Detect XSSdetectXssdetect_xssDetectXSS
Sanitize objectsanitizeObjectsanitize_dictSanitizeObject
Rate limiternew RateLimiter()RateLimiter()NewRateLimiter()
Validate URL (SSRF)validateUrlvalidate_url_ssrfValidateURL
Detect prompt injectiondetectPromptInjectiondetect_prompt_injectionDetectPromptInjection
Correlation window (v1.6)new CorrelationWindow(...)CorrelationWindow(...)v1.7
Detect deserialization (v1.6)detectDeserializationdetect_deserializationv1.7

Go SDK parity caveat. Most runtime middleware (sanitization, rate limit, CSRF, HPP, prompt injection) is at parity across all three SDKs today. The v1.6-only helpers (CorrelationWindow, detectDeserialization, mutation tester, V32-V34) land in Go in v1.7. The Go SDK already picks up all corpus-level improvements (NFKC, multi-decode, new patterns) because Go reads patterns.json at runtime.

Why parity matters

If a payload bypasses one SDK but not the others, it's a bug everywhere, not just in the SDK that missed it. The shared spec means a fix lands in one PR and propagates to all three SDKs at once. The shared test vectors mean the fix gets locked in for every future release.

This is the structural difference between Arcis and tools that bolt second-language SDKs on top of a primary one. Arcjet's Python is a sidecar; Aikido's Python is Django/Flask-only with no FastAPI; Snyk has no runtime SDK. Arcis enforces parity as a contract.