AfterPack Cloud API संदर्भ

api.afterpack.dev का wire contract: authentication, batch obfuscation endpoint, limits, rate limits, build का time budget, और वे diagnostic codes जिन्हें client को संभालना होता है।

एक Pro key configure होते ही @afterpack/core और हर framework plugin यह protocol पहले से बोलते हैं: auth, multipart streaming, retries, सब कुछ। इसे तब पढ़ें जब आप कोई custom CI integration जोड़ रहे हों, official packages के बाहर कोई client लिख रहे हों, या किसी ऐसे response को debug कर रहे हों जिसकी आपके tooling को उम्मीद नहीं थी।

Base URL और versioning

Base URL: https://api.afterpack.dev/v1/

API का version URL में होता है, और v1 ही एकमात्र version है। इसके भीतर response fields जोड़े जाते हैं, कभी हटाए या दूसरे अर्थ में इस्तेमाल नहीं किए जाते; कोई breaking change v2 के रूप में इसके साथ-साथ ship होगा। GET /v1/version deployed version और environment लौटाता है, और GET / बिना authentication वाला liveness check है।

Client compatibility

दो वैकल्पिक request headers, जो न होने या malformed होने पर दोनों ignore किए जाते हैं, कभी 400 नहीं देते — curl script हो या इन headers से पुराना client, किसी पर भी कोई असर नहीं पड़ता:

Headerक्या ले जाता है
X-AfterPack-Client-VersionInstalled @afterpack/core का npm version, उस पर बने client के लिए।
X-AfterPack-ClientCall करने वाला package और उसका version, जैसे afterpack/0.1.0 या @afterpack/vite/0.1.0।

तुलना केवल server-side होती है, MAJOR.MINOR.PATCH पर, किसी भी prerelease suffix को नज़रअंदाज़ करते हुए (0.1.0-rc.3 को 0.1.0 पढ़ा जाता है); ऐसा version जिसे यह server parse नहीं कर सकता, या header का पूरी तरह न होना, हमेशा स्वीकार किया जाता है। जब तक कोई minimum configured है, हर response में X-AfterPack-Min-Client-Version होता है, ताकि script बिना इनकार झेले अपनी स्थिति जाँच सके। यह जाँच key auth के ठीक बाद, request body पढ़े जाने से पहले होती है:

  • Configured minimum से नीचे: 426 DIAG_CLIENT_UPGRADE_REQUIRED, details.minVersion के साथ।
  • Sunset window के दौरान: 410 DIAG_API_SUNSET।

डिफ़ॉल्ट रूप से इनमें से कोई configured नहीं है। Workspace इन्हें तभी देखता है जब AfterPack इस API के लिए कोई minimum version या sunset date सेट करता है।

Response में एक top-level notices array भी हो सकता है: सफल batch-summary पर, किसी भी error body पर, और Free-tier telemetry के 202 पर — {severity, code, message, url?}, अधिकतम 5, हर message 500 characters तक सीमित। अज्ञात severity को warning माना जाता है; इसे दिखाने के अलावा कुछ करने की ज़रूरत नहीं है।

Authentication

दो credentials, और वे एक-दूसरे की जगह इस्तेमाल नहीं हो सकते।

CredentialHeaderयह कहाँ तक पहुँचता है
एक Pro API keyAuthorization: Bearer ap_v1_<...>POST /v1/obfuscate/batch और GET /v1/usage। Key अपना workspace खुद निकाल लेती है, इसलिए कोई workspace id नहीं भेजा जाता।
एक dashboard sessionवह session जो sign in करने के बाद आपके browser में रहता हैवह सब कुछ जो किसी account को manage करता है: keys बनाना, सूचीबद्ध करना और revoke करना, plans, billing, members, projects। एक स्पष्ट workspaceId और एक workspace role लेता है।

Key एक build credential है। यह obfuscate करती है और अपना usage रिपोर्ट करती है, और यह न दूसरी key बना सकती है, न billing पढ़ सकती है, न workspace बदल सकती है। यही सीमा इसका उद्देश्य है: CI में रखी key आपका allowance खर्च कर सकती है, और कुछ नहीं।

Keys ap_v1_ के बाद 40 base62 characters होती हैं। Key ठीक एक बार दिखाई जाती है, बनाते समय। Server-side केवल एक salted HMAC-SHA256 hash रखा जाता है, इसलिए raw key बाद में कभी वापस नहीं मिल सकती, केवल revoke की जा सकती है। इसे dashboard में बनाएँ।

Pro cloud batch-obfuscation request flowYour buildplugin / CLIPOST /v1/obfuscate/batchAuthorization: Bearer ap_…AfterPack cloudobfuscates each fileobfuscation is in-memoryper-file resultsBatch summarycounts + timingYour build outputprotected & written backFiles stream back one by one; the source sent for obfuscation is processed in memory, not stored.

Endpoints

POST /v1/obfuscate/batch

एकमात्र obfuscation endpoint। एक call एक build है। हर फ़ाइल पूरी होते ही उसका result stream होकर वापस आता है।

Request: multipart/form-data।

Partज़रूरीविवरण
batchहाँBatch manifest, एक JSON string part के रूप में।
हर फ़ाइल का एक partहाँJS source, उस partName के तहत जो उसकी manifest entry घोषित करती है।
हर source map का एक partवैकल्पिकएक upstream source map, उस entry के sourceMapPartName के तहत।

Manifest यह है:

{
  "version": "1",
  "files": [
    {
      "filePath": "assets/app-a1b2c3.js",  // echoed back on the result part
      "partName": "file0",                 // names the form part carrying the source
      "sourceMapPartName": "map0",         // optional
      "config": { "regions": [ /* ... */ ] } // optional, per-file
    }
  ],
  "config": { "preset": "hard", "seed": 42 }, // batch-level EngineConfig
  "git": { "commitSha": "…", "ref": "…" }     // optional build attribution
}

Batch-level config एक engine config object है: Configuration पर दी गई हर key, जिसमें preset, seed और regions शामिल हैं। filePath और git manifest-level fields हैं; ऊपर manifest की बनावट देखें।

filePath में quote या CR/LF character नहीं हो सकता। इसे result part के Content-Disposition में ज्यों का त्यों echo किया जाता है, और malformed path अस्वीकार कर दिया जाता है।

curl https://api.afterpack.dev/v1/obfuscate/batch \
  -H "Authorization: Bearer ap_v1_xxx" \
  -F 'batch={"version":"1","files":[{"filePath":"dist/app.js","partName":"file0"}],"config":{"preset":"hard"}}' \
  -F file0=@dist/app.js

Response: 200, streaming multipart/mixed body के साथ। Parts फ़ाइलें पूरी होते ही आते हैं, इसलिए पूरे batch को buffer करने के बजाय हर part आते ही उसे disk पर लिखें:

  1. हर फ़ाइल का एक obfuscation-result part: { version, filePath, status, output, outputMap, processingManifest }। विफलता पर output और outputMap null होते हैं और processingManifest.diagnostics कारण बताता है।
  2. एक अंतिम batch-summary part: { version, totalFiles, successCount, failureCount, engineVersion, results, totalDurationMs, totalInputBytes, totalOutputBytes }।

किसी एक फ़ाइल की विफलता batch को नहीं रोकती। बाकी हर फ़ाइल सामान्य रूप से stream होती रहती है, और summary बताती है कि कितनी सफल और कितनी विफल रहीं।

GET /v1/usage

Workspace का usage और allowance। यह management जैसा एकमात्र read है जो key कर सकती है, ताकि कोई CI job अपना बचा हुआ allowance खुद जाँच सके। यह या तो एक Pro API key (जो अपना workspace खुद निकाल लेती है) या एक dashboard session के साथ ?workspaceId= स्वीकार करता है।

{
  "tier": "indie",
  "workspace": { "id": "…", "name": "…" },
  "allowance": { "remainingMb": 412.5, "totalMb": 500, "resetAt": "…" },
  "credits": { "balanceMb": 20 },
  "subscription": { "status": "active", "plan": "indie_monthly", "renewsAt": "…", "graceUntil": null, "lapsed": false },
  "recentBuilds": [
    {
      "buildId": "…", "builtAt": "…", "fileCount": 61,
      "totalBytes": 3145728, "outputBytes": 9437184,
      "meteredMb": 3.0, "allowanceMb": 3.0, "creditMb": 0, "overageMb": 0,
      "projectId": "…", "cloudMs": 39120
    }
  ]
}

अज्ञात होने पर outputBytes और cloudMs null होते हैं, उनकी जगह कभी 0 नहीं। allowanceMb / creditMb / overageMb तीन pools में meteredMb का बँटवारा हैं।

Limits

Limitमान
प्रति फ़ाइल50 MB
प्रति batch फ़ाइलें200
Batch के कुल bytes500 MB

इनमें से किसी को भी पार करने पर request पूरी की पूरी 413 और DIAG_FILE_TOO_LARGE या DIAG_BATCH_TOO_LARGE के साथ अस्वीकार हो जाती है, कुछ भी meter होने से पहले। Dashboard की ओर से यही संख्याएँ API keys में हैं।

Rate limits

एक rolling 60-second window पर, प्रति key और प्रति client IP गिने जाते हैं:

ScopeLimit
प्रति key, free workspace10 requests / min
प्रति key, paid workspace100 requests / min
प्रति client IP100 requests / min

किसी भी scope को पार करने पर 429 लौटता है, DIAG_RATE_LIMITED और एक Retry-After header के साथ, जो उस समय पर सेट होता है जब तक trigger करने वाली window वास्तव में खाली न हो जाए। यदि rate-limit check खुद नहीं चल पाता, तो request 503 DIAG_RATE_CHECK_UNAVAILABLE और Retry-After: 5 के साथ fail closed होती है।

Build का time budget

पूरा bundle एक ही invocation के भीतर, 120-second CPU limit के तहत obfuscate होता है। दो wall-clock budgets build को उस limit के भीतर रखते हैं।

बीता समयक्या होता है
45 sProtection Map capture रुक जाता है। Obfuscation पूरा होने तक चलता है; stored map को deadline skip reason के साथ partial चिह्नित किया जाता है।
90 sकोई नई फ़ाइल शुरू नहीं की जाती। बाकी हर फ़ाइल DIAG_BUILD_DEADLINE के साथ एक स्पष्ट failure stream करती है, जो बताती है कि N में से कितनी पूरी हुईं, और stream सामान्य रूप से बंद होती है।

अगर आप दूसरे budget तक पहुँचते हैं, तो batch को बाँट दें।

Diagnostic codes

Errors HTTP status के साथ एक स्थिर code लेकर आते हैं, उसी DIAG_* namespace में जिसमें engine के अपने diagnostics हैं। जिन्हें client को संभालना होता है:

CodeStatusअर्थ
DIAG_INVALID_KEY401Key मौजूद नहीं या पहचानी नहीं गई।
DIAG_KEY_REVOKED401Key revoke कर दी गई थी।
DIAG_KEY_EXPIRED401Key अपने expiresAt से आगे निकल चुकी है।
DIAG_KEY_OUT_OF_SCOPE403Key मान्य है, पर उसकी allowedIPs सूची के बाहर के IP से इस्तेमाल हुई।
DIAG_CLIENT_UPGRADE_REQUIRED426Client configured minimum version से नीचे है। details.minVersion साथ आता है। देखें Client compatibility।
DIAG_API_SUNSET410इस API version का sunset हो चुका है। देखें Client compatibility।
DIAG_ENTITLEMENT_LAPSED402Subscription का भुगतान बकाया है। graceUntil और upgradeUrl साथ आते हैं।
DIAG_QUOTA_EXHAUSTED402Allowance + credits (+ overage cap, अगर चालू है) इस build को कवर नहीं कर सकते। remainingMb, requestedMb और एक reason साथ आते हैं, जो "quota ख़त्म" को "overage cap तक पहुँचे" से अलग करता है।
DIAG_RATE_LIMITED429ऊपर rate limits देखें। retryAfterSeconds साथ आता है।
DIAG_RATE_CHECK_UNAVAILABLE503Rate-limit check विफल हुआ; fail closed। Retry करें।
DIAG_INVALID_MANIFEST400Malformed multipart body, batch part मौजूद नहीं, या ऐसा manifest जो validation में fail होता है।
DIAG_FILE_TOO_LARGE413कोई एक फ़ाइल 50 MB से बड़ी।
DIAG_BATCH_TOO_LARGE413200 से ज़्यादा फ़ाइलें या कुल 500 MB से ज़्यादा।
DIAG_BUILD_DEADLINEn/aप्रति फ़ाइल, एक 200 stream के भीतर। इस फ़ाइल के शुरू होने से पहले build का time budget ख़त्म हो गया।
DIAG_ENGINE_FAILUREn/aप्रति फ़ाइल, एक 200 stream के भीतर। इस फ़ाइल पर engine ने error throw किया।

आख़िरी दो HTTP statuses नहीं हैं। वे एक सफल response के भीतर किसी obfuscation-result part पर status: "failure" के रूप में आते हैं। जो client केवल HTTP status देखता है, वह आंशिक रूप से विफल build को साफ़ build समझ बैठेगा।

Retries और backoff

StatusRetry योग्यव्यवहार
400, 401, 402, 403, 413नहींRequest ठीक करें।
429एक बारRetry-After का ठीक-ठीक पालन करें, 120 s तक सीमित; दूसरा 429 fail closed होता है।
500नहींEngine bug; इसे रिपोर्ट करें।
503, 504हाँ1 s, 4 s, 16 s (तीन retries, कुल चार प्रयास), फिर fail closed।

Official client 120-second का whole-request timeout भी लागू करता है, और DNS, TLS तथा connection-reset failures को अनिश्चित काल तक retry करने के बजाय unreachable-cloud मानता है।

Key lifecycle, client की नज़र से

Keys बनाना, उनका scope तय करना और उन्हें revoke करना dashboard operations हैं। इस API को call करने वाले code के लिए दो व्यवहार मायने रखते हैं:

  • Build के बीच revocation। Batch stream होते समय revoke की गई key केवल अगली request पर 401 लौटाती है; जो कुछ पहले से चल रहा है, वह सामान्य रूप से पूरा होता है।
  • IP सूची तक सीमित key कहीं और से इस्तेमाल होने पर 403 DIAG_KEY_OUT_OF_SCOPE लौटाती है, जो अमान्य या revoke की गई key को मिलने वाले 401 से अलग है, ताकि client "गलत key" और "सही key, गलत जगह" में फ़र्क कर सके।
Metering atomic है, और यह सबसे पहले चलती है

जो batch workspace के pools में नहीं समाता, वह किसी भी फ़ाइल के dispatch होने से पहले पूरा का पूरा अस्वीकार हो जाता है, और pools अछूते रहते हैं: कभी आंशिक रूप से process नहीं, कभी आंशिक रूप से bill नहीं। यह fail-closed नियम का batch-level रूप है।

Source code का प्रबंधन

Obfuscation के लिए भेजा गया source केवल memory में, उसी एक request की अवधि तक process होता है, और कभी disk, logs या search index में नहीं लिखा जाता। Logs में request ids, फ़ाइलों की गिनती, bytes का योग और diagnostic codes होते हैं, कभी फ़ाइल contents, identifier names या constant values नहीं।

एक artifact request के बाद भी बना रहता है: dashboard के लिए हर build के साथ stored Protection Map। इसमें आपका मूल source होता है, जो इस आधार पर रंगा होता है कि हर token पर कितना transformation हुआ। यह हर project के लिए डिफ़ॉल्ट रूप से चालू है, केवल मालिक workspace के members ही इसे पढ़ सकते हैं, इसे एक साल और प्रति project आख़िरी 500 builds तक रखा जाता है (जो पहले ख़त्म हो), और इसे project settings में बंद किया जा सकता है। पूरा विवरण Privacy और data handling में है।

आगे

  • Deployment modes: local Free build की तुलना में यह protocol कहाँ फिट होता है।
  • Pro: Pro local engine के ऊपर क्या जोड़ता है।
  • Privacy और data handling: क्या stored होता है, कितने समय तक, और उसे कौन पढ़ सकता है।
  • Tiers: MB allowances, overage, और हर plan इस API पर क्या अनलॉक करता है।
  • API keys: उस credential को बनाना, उसका scope तय करना, rotate और revoke करना जिसे यह API authenticate करता है।
  • CLI reference: official client जो इन नियमों को लागू करता है।
  • Configuration: वह engine config जो config field ले जाता है।