{"_id":"@appattest/capacitor","_rev":"2-f098c331afc670772ada98c5352c0178","name":"@appattest/capacitor","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"@appattest/capacitor","version":"0.1.0","keywords":["capacitor","plugin","native","ios","app-attest","secrets","keychain"],"author":{"name":"Bault LLC"},"license":"MIT","_id":"@appattest/capacitor@0.1.0","maintainers":[{"name":"appattest_engineer","email":"engineering@appattest.dev"}],"homepage":"https://github.com/AppAttest/appAttest-sdk/tree/main/bridges/capacitor#readme","bugs":{"url":"https://github.com/AppAttest/appAttest-sdk/issues"},"dist":{"shasum":"8d7950df89dbd77dfd9ab597a0264f2636430ae8","tarball":"https://registry.npmjs.org/@appattest/capacitor/-/capacitor-0.1.0.tgz","fileCount":21,"integrity":"sha512-NmjZkiPUczOOssNX1z3RwJfp7d/K03Ib0To44vKHOTEqYlMGBehJHdCWJt3sle7QUxXf4+HHCJQFp/2y6PeX1w==","signatures":[{"sig":"MEUCIQCC9sdzDEaGNJnt5ElpBQRzhnUoqYltmt9Oi7WqvQa0jQIgZjFFXuIXwRAhjrpBTFdPzWYJSusaqq1KXUnq2ov7Okg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67044},"main":"dist/plugin.cjs.js","types":"dist/esm/index.d.ts","unpkg":"dist/plugin.js","module":"dist/esm/index.js","gitHead":"82845a5dd905f0e3b5830588e96e8e1b42dbd7b3","scripts":{"fmt":"prettier \"src/**/*.ts\" --write","lint":"eslint . --ext .ts","build":"npm run clean && tsc && rollup -c rollup.config.js","clean":"rimraf ./dist","watch":"tsc --watch","docgen":"docgen --api AppAttestPlugin --output-readme README.md --output-json dist/docs.json","verify":"npm run verify:ios && npm run verify:web","verify:ios":"pod lib lint AppattestCapacitor.podspec --allow-warnings --platforms=ios --include-podspecs=../../AppAttest.podspec,../../AppAttestObjC.podspec || true","verify:web":"npm run build","prepublishOnly":"npm run build"},"_npmUser":{"name":"appattest_engineer","email":"engineering@appattest.dev"},"capacitor":{"ios":{"src":"ios"}},"repository":{"url":"git+https://github.com/AppAttest/appAttest-sdk.git","type":"git","directory":"bridges/capacitor"},"_npmVersion":"11.6.2","description":"Capacitor bridge for AppAttest — App-Attest-gated secret delivery for iOS.","directories":{},"_nodeVersion":"25.2.1","_hasShrinkwrap":false,"devDependencies":{"rimraf":"^5.0.0","rollup":"^4.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@capacitor/ios":"^7.0.0","@capacitor/core":"^7.0.0"},"peerDependencies":{"@capacitor/core":"^6.0.0 || ^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/capacitor_0.1.0_1781140631632_0.27088746872806047","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@appattest/capacitor","version":"0.4.0","description":"Capacitor bridge for AppAttest — App-Attest-gated secret delivery for iOS.","main":"dist/plugin.cjs.js","module":"dist/esm/index.js","types":"dist/esm/index.d.ts","unpkg":"dist/plugin.js","scripts":{"verify":"npm run verify:ios && npm run verify:web","verify:ios":"pod lib lint AppattestCapacitor.podspec --allow-warnings --platforms=ios --include-podspecs=../../AppAttest.podspec,../../AppAttestObjC.podspec || true","verify:web":"npm run build","lint":"eslint . --ext .ts","fmt":"prettier \"src/**/*.ts\" --write","docgen":"docgen --api AppAttestPlugin --output-readme README.md --output-json dist/docs.json","build":"npm run clean && tsc && rollup -c rollup.config.js","clean":"rimraf ./dist","watch":"tsc --watch","prepublishOnly":"npm run build"},"keywords":["capacitor","plugin","native","ios","app-attest","secrets","keychain"],"repository":{"type":"git","url":"git+https://github.com/AppAttest/appAttest-sdk.git","directory":"bridges/capacitor"},"author":{"name":"Bault LLC"},"license":"MIT","bugs":{"url":"https://github.com/AppAttest/appAttest-sdk/issues"},"homepage":"https://github.com/AppAttest/appAttest-sdk/tree/main/bridges/capacitor#readme","peerDependencies":{"@capacitor/core":"^6.0.0 || ^7.0.0"},"devDependencies":{"@capacitor/core":"^7.0.0","@capacitor/ios":"^7.0.0","@types/node":"^20.0.0","rimraf":"^5.0.0","rollup":"^4.0.0","typescript":"^5.4.0"},"capacitor":{"ios":{"src":"ios"}},"gitHead":"6e0e75fffd7cdef60658adf5c53fbb9be0f2b7db","_id":"@appattest/capacitor@0.4.0","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-vLLIjspBxanCJCP0W1moiAUatbMDn/XBx8Vqxj1IzBCyREzajQHo/ayxEx0pHFc6mlB0zWnO9Uv471zpoUaoPQ==","shasum":"99b0f4fab45a92443c99729f366470cf3ee7f777","tarball":"https://registry.npmjs.org/@appattest/capacitor/-/capacitor-0.4.0.tgz","fileCount":21,"unpackedSize":72898,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDptdfPTfQhIP08p4DF0mctW8Xi/3OXJYvdE+sAXUEsOAIhAIC3ubqBhn4QMqA2KzMlrSukbCe9axy24zvmPLHGSrOD"}]},"_npmUser":{"name":"appattest_engineer","email":"engineering@appattest.dev"},"directories":{},"maintainers":[{"name":"appattest_engineer","email":"engineering@appattest.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/capacitor_0.4.0_1784157229552_0.5764356952904028"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-11T01:17:11.436Z","modified":"2026-07-15T23:13:49.899Z","0.1.0":"2026-06-11T01:17:11.763Z","0.4.0":"2026-07-15T23:13:49.712Z"},"bugs":{"url":"https://github.com/AppAttest/appAttest-sdk/issues"},"author":{"name":"Bault LLC"},"license":"MIT","homepage":"https://github.com/AppAttest/appAttest-sdk/tree/main/bridges/capacitor#readme","keywords":["capacitor","plugin","native","ios","app-attest","secrets","keychain"],"repository":{"type":"git","url":"git+https://github.com/AppAttest/appAttest-sdk.git","directory":"bridges/capacitor"},"description":"Capacitor bridge for AppAttest — App-Attest-gated secret delivery for iOS.","maintainers":[{"name":"appattest_engineer","email":"engineering@appattest.dev"}],"readme":"# @appattest/capacitor\n\nCapacitor bridge for [AppAttest](https://www.appattest.dev) — App-Attest-gated\nsecret delivery for iOS.\n\n> Ships in lockstep with the Swift SDK (current: `v0.4.0`).\n\n## Platform support\n\n- **iOS 17+** — full support. Uses Apple's `DCAppAttestService` via the\n  native AppAttest Swift SDK.\n- **Web** — not supported. Calls throw `AppAttestError` with code\n  `attestation_rejected` (there's no equivalent platform guarantee on web).\n- **Android** — not supported (App Attest is iOS-only).\n\nCapacitor 6 and 7 are both supported (peer-dep `^6 || ^7`).\n\n## Install\n\n```bash\nnpm install @appattest/capacitor\nnpx cap sync\n```\n\nThe iOS pod depends on `AppAttestObjC` (a companion pod from the same\nmonorepo), wired automatically through the pod's `s.dependency`.\n\n## Quick start\n\n```ts\nimport { AppAttest } from '@appattest/capacitor';\n\n// Once, at app launch:\nAppAttest.start('production');\n\n// Anywhere:\nawait AppAttest.waitForReady();\nconst key = await AppAttest.getSecret('OPENAI_API_KEY'); // string | null\nconst all = await AppAttest.getAllSecrets();             // Record<string, string>\n```\n\n`start(release)` is fire-and-forget: the first launch attests the device once\n(persists across launches), then syncs secrets; later launches hydrate\nfrom the Keychain and re-sync in the background. Foreground re-entry\nre-syncs automatically — your app does no lifecycle wiring.\n\n## State\n\n```ts\nconst s = await AppAttest.getState(); // { name, error? }\n\nconst handle = await AppAttest.addStateListener((s) => console.log(s.name));\n// later: handle.remove();  — or drop everything:\nawait AppAttest.removeAllListeners();\n```\n\n`state.name` is one of `'initializing' | 'attesting' | 'syncing' | 'ready' |\n'subscription_required' | 'credits_required' | 'unavailable'`. The\nnon-`ready` terminal states carry `state.error`.\n\n**End-user-facing apps:** show a generic \"temporarily unavailable\" notice\nfor the non-`ready` terminal states. **Developer / staff builds:** log the\nfull error (including `actionUrl`) so the developer knows whether to\nsubscribe, top up, or investigate.\n\n## Refresh & recovery\n\n```ts\nawait AppAttest.retry();            // re-run the sync (no re-attestation)\nawait AppAttest.invalidateBundle(); // drop the cached bundle, force a fresh sync\nawait AppAttest.reset();            // full wipe; next start(release) re-attests\n```\n\n`retry()` recovers from transient failures. `invalidateBundle()` forces\nfresh secret bytes when you don't want to wait for the next rotation\npickup. `reset()` is the nuclear option, for sign-out / data-clearing flows.\n\n## Debug mode (simulator, tests, CI)\n\nThe simulator can't produce a real App Attest attestation. Use local stubs:\n\n```ts\nif (process.env.NODE_ENV !== 'production') {\n  await AppAttest.setDebugMode('local', {\n    OPENAI_API_KEY: 'sk-test-stub',\n  });\n}\nAppAttest.start('staging');\n```\n\nPass `null` to return to real attestation. The native debug surface is\n`#if DEBUG`-gated — physically absent from Release builds, which always\nrun real attestation; calling it there rejects with\n`debug_mode_release_blocked`.\n\nDev builds on **real devices** don't need debug mode — they attest for\nreal and read the sandbox column (below).\n\n## Buckets and columns\n\nTwo independent axes. Keeping them apart is the whole model.\n\n**1. Which server bucket you declare — you choose it, explicitly.**\n\n`release` is a **required** argument on `AppAttest.start(release)`. There\nis no default, and no inference from build flavor. The bucket is exactly\nwhat you pass:\n\n```ts\nawait AppAttest.start('production'); // shipping build\nawait AppAttest.start('staging');    // pre-ship verification build\n```\n\n`'staging'` and `'production'` are two functionally-identical,\nseparately-keyed, **metered** buckets. Neither is free.\n\n**2. Which secrets column Apple puts you in — the AAGUID decides, not you.**\n\nApple's App Attest AAGUID is a build-time property stamped into every\nattestation, and you cannot forge it:\n\n- **Development-signed builds** (Xcode → device) → **sandbox** column.\n- **Distribution builds** carrying the production App Attest entitlement\n  (TestFlight, App Store) → **production** column.\n\nThe two axes are orthogonal: **both servers have both columns.** Edge\nresolves your declared bucket against the AAGUID. A development-signed\nbuild declaring `'production'` is rejected with a loud\n`403 bucket_not_permitted` — never silently re-routed.\n\nFor last-mile verification of production secrets before submitting to the\nApp Store, use TestFlight: it carries the real production AAGUID, so it\nreads the production column. There is no debug-build path to the\nproduction column.\n\n## Error handling\n\nAll methods reject with `AppAttestError` (`code`, plus `subscribeUrl` /\n`topupUrl` / `actionUrl` on the billing cases):\n\n```ts\nimport { AppAttest, AppAttestError, ErrorCode } from '@appattest/capacitor';\n\ntry {\n  await AppAttest.waitForReady();\n} catch (e) {\n  if (e instanceof AppAttestError && e.code === ErrorCode.SubscriptionRequired) {\n    console.log('project needs a subscription:', e.actionUrl);\n  }\n}\n```\n\n| Code | Meaning |\n|------|---------|\n| `subscription_required` | Project subscription not active (`subscribeUrl`). |\n| `credits_required` | Allowance exhausted and balance empty (`topupUrl`). |\n| `attestation_rejected` | Apple or AppAttest rejected this install (also thrown on web) — terminal until reinstall. |\n| `service_unavailable` | Temporary service condition; retryable (the SDK backs off automatically). |\n| `network` | Device-side transport failure; retryable. |\n| `debug_mode_release_blocked` | `setDebugMode` called in a Release build. |\n| `invalid_argument` | Malformed call input. |\n\n## License\n\nMIT © 2026 Bault LLC. See [LICENSE](LICENSE).\n","readmeFilename":"README.md"}