@pyric/cli 0.1.0-alpha.26 → 0.1.0-alpha.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/assurance/.generated/conformance-verdicts.d.ts +5 -0
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +5 -0
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/assurance/capabilities.d.ts.map +1 -1
- package/dist/assurance/capabilities.js +24 -5
- package/dist/assurance/capabilities.js.map +1 -1
- package/dist/assurance/runner.d.ts.map +1 -1
- package/dist/assurance/runner.js +37 -50
- package/dist/assurance/runner.js.map +1 -1
- package/dist/assurance/types.d.ts +5 -0
- package/dist/assurance/types.d.ts.map +1 -1
- package/dist/assurance/types.js.map +1 -1
- package/dist/assurance/validation.d.ts +2 -16
- package/dist/assurance/validation.d.ts.map +1 -1
- package/dist/assurance/validation.js +121 -1
- package/dist/assurance/validation.js.map +1 -1
- package/dist/bridge/surface/arguments/assurance.d.ts +31 -6
- package/dist/bridge/surface/arguments/assurance.d.ts.map +1 -1
- package/dist/bridge/surface/arguments/assurance.js +1 -0
- package/dist/bridge/surface/arguments/assurance.js.map +1 -1
- package/dist/bridge/surface/arguments/messaging.d.ts +2 -2
- package/dist/bridge/surface/methods/assurance/define.d.ts +2 -2
- package/dist/bridge/surface/methods/assurance/map.d.ts +29 -6
- package/dist/bridge/surface/methods/assurance/map.d.ts.map +1 -1
- package/dist/bridge/surface/methods/assurance/propose.d.ts +7 -0
- package/dist/bridge/surface/methods/assurance/propose.d.ts.map +1 -1
- package/dist/bridge/surface/methods/messaging/send.d.ts +4 -4
- package/dist/bridge/surface/render/discriminator-schemas.d.ts +6 -6
- package/dist/cli/database-rules.js +1 -1
- package/dist/cli/database-rules.js.map +1 -1
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +28 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/pyric-config.d.ts +8 -0
- package/dist/cli/pyric-config.d.ts.map +1 -1
- package/dist/cli/pyric-config.js.map +1 -1
- package/dist/cli/run.d.ts +42 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +115 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +5 -3
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/verify.d.ts +6 -0
- package/dist/cli/verify.d.ts.map +1 -1
- package/dist/cli/verify.js +240 -15
- package/dist/cli/verify.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +1 -1
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
- package/dist/conformance/.generated/conformance-docs.js +1 -1
- package/dist/conformance/.generated/conformance-docs.js.map +1 -1
- package/dist/remote/local-storage-url.d.ts +2 -15
- package/dist/remote/local-storage-url.d.ts.map +1 -1
- package/dist/remote/local-storage-url.js +1 -60
- package/dist/remote/local-storage-url.js.map +1 -1
- package/dist/serve/assets/avatar-route.d.ts.map +1 -1
- package/dist/serve/assets/avatar-route.js +6 -6
- package/dist/serve/assets/avatar-route.js.map +1 -1
- package/dist/serve/assets/resolver.d.ts +3 -0
- package/dist/serve/assets/resolver.d.ts.map +1 -1
- package/dist/serve/assets/resolver.js +1 -1
- package/dist/serve/assets/resolver.js.map +1 -1
- package/dist/serve/entries/app-client.d.ts.map +1 -1
- package/dist/serve/entries/app-client.js +6 -0
- package/dist/serve/entries/app-client.js.map +1 -1
- package/dist/serve/repro/denials.d.ts.map +1 -1
- package/dist/serve/repro/denials.js +2 -1
- package/dist/serve/repro/denials.js.map +1 -1
- package/dist/serve/site-ui/_astro/{app.DFdWhpVY.js → app.BCNb6gMq.js} +1 -1
- package/dist/serve/site-ui/_astro/app.DhoRPDdN.js +147 -0
- package/dist/serve/site-ui/_astro/{seed.vvXV1ioI.js → seed.BO5CXcqE.js} +1 -1
- package/dist/serve/site-ui/auth/index.html +1 -1
- package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
- package/dist/serve/site-ui/docs/ai-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/api-reference/index.html +2 -1
- package/dist/serve/site-ui/docs/api-reference.md +1 -0
- package/dist/serve/site-ui/docs/app-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/auth-compat/index.html +2 -2
- package/dist/serve/site-ui/docs/auth-compat.md +1 -1
- package/dist/serve/site-ui/docs/auth-flutter-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/auth-kotlin-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/auth-swift-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +1 -1
- package/dist/serve/site-ui/docs/build/authentication/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +13 -2
- package/dist/serve/site-ui/docs/build/cloud-storage.md +23 -0
- package/dist/serve/site-ui/docs/build/default-avatars/index.html +1 -1
- package/dist/serve/site-ui/docs/build/inspect-activity/index.html +1 -1
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
- package/dist/serve/site-ui/docs/conformance-scores/index.html +1 -1
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/database-compat/index.html +5 -1
- package/dist/serve/site-ui/docs/database-compat.md +4 -0
- package/dist/serve/site-ui/docs/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/docs/examples/index.html +1 -1
- package/dist/serve/site-ui/docs/firestore-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/firestore-kotlin-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/firestore-swift-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/flutter/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/nextjs/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/node-host/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +2 -1
- package/dist/serve/site-ui/docs/get-started/start-building.md +2 -0
- package/dist/serve/site-ui/docs/get-started/vite/index.html +4 -2
- package/dist/serve/site-ui/docs/get-started/vite.md +4 -0
- package/dist/serve/site-ui/docs/index.json +50 -0
- package/dist/serve/site-ui/docs/messaging-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities/index.html +1 -1
- package/dist/serve/site-ui/docs/overview/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-app-check-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-data-connect-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-eventarc-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-extensions-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-functions-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-installations-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-instance-id-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-machine-learning-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-phone-number-verification-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-project-management-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-remote-config-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-security-rules-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +2 -2
- package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +24 -5
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api.md +11 -4
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-flow-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-client-app-bridge-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-client-app-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-client-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-client-database-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-client-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-client-storage-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-repro-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +16 -3
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +11 -10
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +17 -3
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +7 -5
- package/dist/serve/site-ui/docs/pyric-cli-vite-ssr-loader-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-branches-store-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-checkpoints-directory-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-checkpoints-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-storage-sw-reference-api/index.html +102 -0
- package/dist/serve/site-ui/docs/pyric-storage-sw-reference-api.md +76 -0
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-listener-owner-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/reference/cli/index.html +12 -2
- package/dist/serve/site-ui/docs/reference/cli.md +24 -0
- package/dist/serve/site-ui/docs/rtdb-flutter-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/rtdb-kotlin-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/rtdb-swift-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/rules-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rtdb-rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +2 -2
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite.md +1 -1
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +5 -2
- package/dist/serve/site-ui/docs/ship/ship-to-production.md +7 -1
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
- package/dist/serve/site-ui/docs/storage-compat/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
- package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
- package/dist/serve/site-ui/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/firestore/index.html +1 -1
- package/dist/serve/site-ui/llms.txt +1 -0
- package/dist/serve/site-ui/rtdb/index.html +1 -1
- package/dist/serve/site-ui/settings/index.html +1 -1
- package/dist/serve/site-ui/storage/index.html +1 -1
- package/dist/serve/site-ui/studio/index.html +1 -1
- package/dist/serve/site-ui/traffic/index.html +1 -1
- package/dist/serve/verify-hint.d.ts +2 -0
- package/dist/serve/verify-hint.d.ts.map +1 -0
- package/dist/serve/verify-hint.js +10 -0
- package/dist/serve/verify-hint.js.map +1 -0
- package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
- package/dist/serve/vite-generation-rules-watch.js +5 -3
- package/dist/serve/vite-generation-rules-watch.js.map +1 -1
- package/dist/serve/vite-plugin.d.ts +6 -0
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +11 -1
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-service-worker.d.ts +12 -0
- package/dist/serve/vite-service-worker.d.ts.map +1 -0
- package/dist/serve/vite-service-worker.js +33 -0
- package/dist/serve/vite-service-worker.js.map +1 -0
- package/dist/serve/worker/client/auth.d.ts.map +1 -1
- package/dist/serve/worker/client/auth.js +4 -3
- package/dist/serve/worker/client/auth.js.map +1 -1
- package/dist/serve/worker/host/auth-action-codes.js +2 -2
- package/dist/serve/worker/host/auth-action-codes.js.map +1 -1
- package/dist/serve/worker/host/auth-custom-token.d.ts.map +1 -1
- package/dist/serve/worker/host/auth-custom-token.js +4 -2
- package/dist/serve/worker/host/auth-custom-token.js.map +1 -1
- package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
- package/dist/serve/worker/host/dispatch.js +3 -1
- package/dist/serve/worker/host/dispatch.js.map +1 -1
- package/dist/serve/worker/host-auth.d.ts +6 -0
- package/dist/serve/worker/host-auth.d.ts.map +1 -1
- package/dist/serve/worker/host-auth.js +16 -5
- package/dist/serve/worker/host-auth.js.map +1 -1
- package/dist/serve/worker/inbound-validation.d.ts.map +1 -1
- package/dist/serve/worker/inbound-validation.js +1 -0
- package/dist/serve/worker/inbound-validation.js.map +1 -1
- package/dist/serve/worker/protocol/storage.d.ts +1 -8
- package/dist/serve/worker/protocol/storage.d.ts.map +1 -1
- package/dist/serve/worker/protocol/storage.js +2 -14
- package/dist/serve/worker/protocol/storage.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +2 -0
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/verify/index.d.ts +16 -2
- package/dist/verify/index.d.ts.map +1 -1
- package/dist/verify/index.js +100 -18
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/staging/engine.d.ts +102 -0
- package/dist/verify/staging/engine.d.ts.map +1 -0
- package/dist/verify/staging/engine.js +371 -0
- package/dist/verify/staging/engine.js.map +1 -0
- package/dist/verify/staging/rest.d.ts +68 -0
- package/dist/verify/staging/rest.d.ts.map +1 -0
- package/dist/verify/staging/rest.js +93 -0
- package/dist/verify/staging/rest.js.map +1 -0
- package/dist/verify/staging/target.d.ts +39 -0
- package/dist/verify/staging/target.d.ts.map +1 -0
- package/dist/verify/staging/target.js +117 -0
- package/dist/verify/staging/target.js.map +1 -0
- package/package.json +12 -8
- package/src/assurance/.generated/conformance-verdicts.ts +5 -0
- package/src/assurance/capabilities.ts +22 -4
- package/src/assurance/runner.ts +40 -58
- package/src/assurance/types.ts +3 -0
- package/src/assurance/validation.ts +137 -0
- package/src/bridge/surface/arguments/assurance.ts +1 -0
- package/src/cli/database-rules.ts +1 -1
- package/src/cli/index.ts +28 -3
- package/src/cli/pyric-config.ts +5 -0
- package/src/cli/run.ts +139 -0
- package/src/cli/serve.ts +6 -3
- package/src/cli/verify.ts +244 -18
- package/src/conformance/.generated/can-i-use.ts +1 -1
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/remote/local-storage-url.ts +1 -58
- package/src/serve/assets/avatar-route.ts +6 -7
- package/src/serve/assets/resolver.ts +4 -1
- package/src/serve/entries/app-client.ts +7 -0
- package/src/serve/repro/denials.ts +2 -1
- package/src/serve/verify-hint.ts +8 -0
- package/src/serve/vite-generation-rules-watch.ts +6 -3
- package/src/serve/vite-plugin.ts +15 -1
- package/src/serve/vite-service-worker.ts +44 -0
- package/src/serve/worker/client/auth.ts +4 -3
- package/src/serve/worker/host/auth-action-codes.ts +2 -2
- package/src/serve/worker/host/auth-custom-token.ts +4 -2
- package/src/serve/worker/host/dispatch.ts +2 -0
- package/src/serve/worker/host-auth.ts +18 -5
- package/src/serve/worker/inbound-validation.ts +1 -0
- package/src/serve/worker/protocol/storage.ts +2 -14
- package/src/serve/worker/protocol.ts +2 -0
- package/src/verify/index.ts +119 -19
- package/src/verify/staging/engine.ts +455 -0
- package/src/verify/staging/rest.ts +129 -0
- package/src/verify/staging/target.ts +137 -0
- package/dist/serve/site-ui/_astro/app.BpEphDR7.js +0 -147
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal Realtime Database REST client for the staging engine: data reads
|
|
3
|
+
* and writes as admin or as an application user (`auth_variable_override`),
|
|
4
|
+
* and the rules endpoint (`/.settings/rules.json`).
|
|
5
|
+
*
|
|
6
|
+
* Production applies an `auth_variable_override` object as the rules `auth`
|
|
7
|
+
* variable, `auth.token` claims included; the identity capture recorded in
|
|
8
|
+
* `packages/conformance/observations/rtdb-staging/rtdb-staging-auth-override.json`
|
|
9
|
+
* pins that for every field the engine passes.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** The rules `auth` variable a request runs as; `null` is signed out. Absent is admin. */
|
|
13
|
+
export type RtdbAuthOverride = Record<string, unknown> | null;
|
|
14
|
+
|
|
15
|
+
export interface RtdbRestResponse {
|
|
16
|
+
status: number;
|
|
17
|
+
/** Parsed JSON body, or the raw text when it is not JSON. */
|
|
18
|
+
body: unknown;
|
|
19
|
+
text: string;
|
|
20
|
+
/** The `ETag` of the location, when the request asked for it (`etag: true`). */
|
|
21
|
+
etag?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RtdbRestRequest {
|
|
25
|
+
/** Run as this `auth`; absent runs as admin. */
|
|
26
|
+
auth?: RtdbAuthOverride;
|
|
27
|
+
/** REST query parameters (`orderBy`, `startAt`, ...), already JSON-encoded where REST requires it. */
|
|
28
|
+
query?: Record<string, string>;
|
|
29
|
+
/** `export` returns priorities as `.priority` keys. */
|
|
30
|
+
format?: 'export';
|
|
31
|
+
shallow?: boolean;
|
|
32
|
+
/** Ask for the location's `ETag` (a read), for a later conditional write. */
|
|
33
|
+
etag?: boolean;
|
|
34
|
+
/** Write only if the location's `ETag` is still this one; production answers 412 otherwise. */
|
|
35
|
+
ifMatch?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type FetchLike = (url: string, init: { method: string; headers: Record<string, string>; body?: string }) => Promise<{
|
|
39
|
+
status: number;
|
|
40
|
+
text(): Promise<string>;
|
|
41
|
+
headers?: { get(name: string): string | null };
|
|
42
|
+
}>;
|
|
43
|
+
|
|
44
|
+
export class RtdbRestClient {
|
|
45
|
+
readonly databaseUrl: string;
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
databaseUrl: string,
|
|
49
|
+
private readonly token: () => Promise<string>,
|
|
50
|
+
private readonly fetchImpl: FetchLike = (url, init) => fetch(url, init),
|
|
51
|
+
) {
|
|
52
|
+
this.databaseUrl = databaseUrl.replace(/\/+$/, '');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get(path: string, request: RtdbRestRequest = {}): Promise<RtdbRestResponse> {
|
|
56
|
+
return this.send('GET', path, undefined, request);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
put(path: string, value: unknown, request: RtdbRestRequest = {}): Promise<RtdbRestResponse> {
|
|
60
|
+
return this.send('PUT', path, JSON.stringify(value), request);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
patch(path: string, value: unknown, request: RtdbRestRequest = {}): Promise<RtdbRestResponse> {
|
|
64
|
+
return this.send('PATCH', path, JSON.stringify(value), request);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
delete(path: string, request: RtdbRestRequest = {}): Promise<RtdbRestResponse> {
|
|
68
|
+
return this.send('DELETE', path, undefined, request);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The deployed rules as stored, comments included. */
|
|
72
|
+
async getRulesText(): Promise<string> {
|
|
73
|
+
const res = await this.rules('GET');
|
|
74
|
+
if (res.status !== 200) throw new Error(`reading the rules of ${this.databaseUrl} failed: HTTP ${res.status} ${res.text.slice(0, 200)}`);
|
|
75
|
+
return res.text;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Deploy `source` as the rules, or validate it without deploying (`dryRun`). */
|
|
79
|
+
putRules(source: string, options: { dryRun?: boolean } = {}): Promise<RtdbRestResponse> {
|
|
80
|
+
return this.rules('PUT', source, options.dryRun === true);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private async rules(method: 'GET' | 'PUT', body?: string, dryRun = false): Promise<RtdbRestResponse> {
|
|
84
|
+
const url = `${this.databaseUrl}/.settings/rules.json${dryRun ? '?dryRun=true' : ''}`;
|
|
85
|
+
return this.fetchResponse(url, method, body);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async send(method: string, path: string, body: string | undefined, request: RtdbRestRequest): Promise<RtdbRestResponse> {
|
|
89
|
+
const params = new URLSearchParams();
|
|
90
|
+
if (request.auth !== undefined) params.set('auth_variable_override', JSON.stringify(request.auth));
|
|
91
|
+
if (request.format) params.set('format', request.format);
|
|
92
|
+
if (request.shallow) params.set('shallow', 'true');
|
|
93
|
+
for (const [key, value] of Object.entries(request.query ?? {})) params.set(key, value);
|
|
94
|
+
const query = params.toString();
|
|
95
|
+
const url = `${this.databaseUrl}${restPath(path) || '/'}.json${query ? `?${query}` : ''}`;
|
|
96
|
+
const headers: Record<string, string> = {};
|
|
97
|
+
if (request.etag) headers['X-Firebase-ETag'] = 'true';
|
|
98
|
+
if (request.ifMatch !== undefined) headers['if-match'] = request.ifMatch;
|
|
99
|
+
return this.fetchResponse(url, method, body, headers);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private async fetchResponse(url: string, method: string, body?: string, extra: Record<string, string> = {}): Promise<RtdbRestResponse> {
|
|
103
|
+
const res = await this.fetchImpl(url, {
|
|
104
|
+
method,
|
|
105
|
+
headers: { Authorization: `Bearer ${await this.token()}`, 'Content-Type': 'application/json', ...extra },
|
|
106
|
+
...(body === undefined ? {} : { body }),
|
|
107
|
+
});
|
|
108
|
+
const text = await res.text();
|
|
109
|
+
let parsed: unknown = text;
|
|
110
|
+
try {
|
|
111
|
+
parsed = JSON.parse(text);
|
|
112
|
+
} catch {
|
|
113
|
+
// Not JSON: keep the text.
|
|
114
|
+
}
|
|
115
|
+
const etag = res.headers?.get('etag') ?? undefined;
|
|
116
|
+
return { status: res.status, body: parsed, text, ...(etag ? { etag } : {}) };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** `/a/b` for any of `a/b`, `/a/b/`, `a//b`; the root is the empty string. */
|
|
121
|
+
export function restPath(path: string): string {
|
|
122
|
+
const segments = path.split('/').filter(Boolean).map(encodeURIComponent);
|
|
123
|
+
return segments.length === 0 ? '' : `/${segments.join('/')}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Whether a REST status is the rules denying the request. */
|
|
127
|
+
export function isRestDenial(status: number): boolean {
|
|
128
|
+
return status === 401 || status === 403;
|
|
129
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The staging target `pyric verify --engine staging` replays against, from
|
|
3
|
+
* the project's `pyric.json`:
|
|
4
|
+
*
|
|
5
|
+
* { "verify": { "staging": { "project": "my-staging", "rtdb": "https://my-verify.firebaseio.com" } } }
|
|
6
|
+
*
|
|
7
|
+
* `rtdb` is a database URL or an instance name (`my-verify` resolves to
|
|
8
|
+
* `https://my-verify.firebaseio.com`; an instance outside us-central1 needs
|
|
9
|
+
* its full URL). The user brings the instance; pyric provisions nothing.
|
|
10
|
+
*
|
|
11
|
+
* An instance the app's own `firebase.json` deploys rules to, or the app
|
|
12
|
+
* project's default instance, is refused: those hold the app's data.
|
|
13
|
+
*/
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
import { resolveDatabaseInstance } from 'pyric/sandbox/internal';
|
|
17
|
+
|
|
18
|
+
import { firebaseToolsConfigstorePath } from '../../cli/firebase-project.js';
|
|
19
|
+
import type { FirebaseJson } from '../../cli/firebase-json.js';
|
|
20
|
+
import { resolveScope, SERVICE_ACCOUNT_BASE64_ENV_KEY, SERVICE_ACCOUNT_FILE_ENV_KEY } from '../../credentials/node/scope.js';
|
|
21
|
+
|
|
22
|
+
export interface StagingTarget {
|
|
23
|
+
projectId: string;
|
|
24
|
+
databaseUrl: string;
|
|
25
|
+
/** The instance name the URL names. */
|
|
26
|
+
instance: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class StagingConfigError extends Error {
|
|
30
|
+
constructor(message: string) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = 'StagingConfigError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const CONFIG_EXAMPLE = '{ "verify": { "staging": { "project": "<staging project id>", "rtdb": "https://<dedicated instance>.firebaseio.com" } } }';
|
|
37
|
+
|
|
38
|
+
/** The staging target in a parsed `pyric.json`, or a config error naming what is missing. */
|
|
39
|
+
export function stagingTargetFrom(config: unknown): StagingTarget {
|
|
40
|
+
const staging = (config as { verify?: { staging?: unknown } } | null)?.verify?.staging;
|
|
41
|
+
if (staging === undefined) {
|
|
42
|
+
throw new StagingConfigError(`no staging target. Add one to pyric.json: ${CONFIG_EXAMPLE}`);
|
|
43
|
+
}
|
|
44
|
+
const { project, rtdb } = (staging ?? {}) as { project?: unknown; rtdb?: unknown };
|
|
45
|
+
if (typeof project !== 'string' || project.trim() === '') {
|
|
46
|
+
throw new StagingConfigError(`pyric.json verify.staging.project must name the staging project: ${CONFIG_EXAMPLE}`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof rtdb !== 'string' || rtdb.trim() === '') {
|
|
49
|
+
throw new StagingConfigError(`pyric.json verify.staging.rtdb must name the dedicated instance: ${CONFIG_EXAMPLE}`);
|
|
50
|
+
}
|
|
51
|
+
const trimmed = rtdb.trim();
|
|
52
|
+
const databaseUrl = /^[a-z0-9-]+$/i.test(trimmed) ? `https://${trimmed}.firebaseio.com` : trimmed.replace(/\/+$/, '');
|
|
53
|
+
let instance: string | undefined;
|
|
54
|
+
try {
|
|
55
|
+
instance = resolveDatabaseInstance(databaseUrl)?.name;
|
|
56
|
+
} catch {
|
|
57
|
+
instance = undefined;
|
|
58
|
+
}
|
|
59
|
+
if (instance === undefined) {
|
|
60
|
+
throw new StagingConfigError(`pyric.json verify.staging.rtdb "${rtdb}" is not a Realtime Database URL or instance name.`);
|
|
61
|
+
}
|
|
62
|
+
return { projectId: project.trim(), databaseUrl, instance };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Refuse a staging instance the app uses: one `firebase.json` deploys rules
|
|
67
|
+
* to (by instance or by a `.firebaserc` target), or the default instance of
|
|
68
|
+
* the app's project.
|
|
69
|
+
*/
|
|
70
|
+
export function assertNotAppInstance(
|
|
71
|
+
target: StagingTarget,
|
|
72
|
+
app: { firebaseJson: FirebaseJson | null; appProjectId?: string; targetInstances?: string[] },
|
|
73
|
+
): void {
|
|
74
|
+
const declared = new Set<string>(app.targetInstances ?? []);
|
|
75
|
+
const database = app.firebaseJson?.database as unknown;
|
|
76
|
+
const entries = Array.isArray(database) ? database : database ? [database] : [];
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
const instance = (entry as { instance?: unknown }).instance;
|
|
79
|
+
if (typeof instance === 'string') declared.add(instance);
|
|
80
|
+
}
|
|
81
|
+
if (app.appProjectId) declared.add(`${app.appProjectId}-default-rtdb`);
|
|
82
|
+
if (declared.has(target.instance)) {
|
|
83
|
+
throw new StagingConfigError(
|
|
84
|
+
`refusing staging instance ${target.instance}: the app uses it (firebase.json deploys rules to it, or it is the default instance of project ${app.appProjectId}). The staging engine replaces an instance's rules and data, so it needs one dedicated to it.`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* An OAuth token for the staging project: a service account or Application
|
|
91
|
+
* Default Credentials (`resolveScope`), else the Firebase CLI's login
|
|
92
|
+
* (`firebase login`) while its access token is fresh.
|
|
93
|
+
*/
|
|
94
|
+
export async function stagingToken(
|
|
95
|
+
projectId: string,
|
|
96
|
+
deps: { resolve?: typeof resolveScope; env?: NodeJS.ProcessEnv; now?: () => number } = {},
|
|
97
|
+
): Promise<{ token: () => Promise<string>; source: string }> {
|
|
98
|
+
const env = deps.env ?? process.env;
|
|
99
|
+
try {
|
|
100
|
+
const { scope, source } = await (deps.resolve ?? resolveScope)({ projectId, ...(deps.env ? { env: deps.env } : {}) });
|
|
101
|
+
return { token: () => scope.resolveToken(), source };
|
|
102
|
+
} catch (resolveError) {
|
|
103
|
+
// A configured credential that fails is an error to fix, not a reason to
|
|
104
|
+
// run as the developer's own CLI login instead.
|
|
105
|
+
if (configuredCredential(env)) throw resolveError;
|
|
106
|
+
const cli = firebaseCliToken(env, (deps.now ?? Date.now)());
|
|
107
|
+
if (cli !== undefined) return { token: async () => cli, source: 'firebase login' };
|
|
108
|
+
throw new StagingConfigError(
|
|
109
|
+
`no credentials for staging project ${projectId}. ${resolveError instanceof Error ? resolveError.message : String(resolveError)} ` +
|
|
110
|
+
'Or sign in with `firebase login`: its token is used while it has at least 15 minutes left (run any firebase command to refresh it).',
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Whether the environment names a service account (`resolveScope`'s first two sources). */
|
|
116
|
+
function configuredCredential(env: NodeJS.ProcessEnv): boolean {
|
|
117
|
+
return [SERVICE_ACCOUNT_BASE64_ENV_KEY, SERVICE_ACCOUNT_FILE_ENV_KEY].some((key) => (env[key] ?? '').trim() !== '');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** How long a CLI token must stay valid for a run to start with it; it cannot be refreshed mid-run. */
|
|
121
|
+
export const CLI_TOKEN_MARGIN_MS = 15 * 60_000;
|
|
122
|
+
|
|
123
|
+
/** The Firebase CLI's access token, when its configstore holds one with a known expiry at least the margin away. */
|
|
124
|
+
function firebaseCliToken(env: NodeJS.ProcessEnv, now: number): string | undefined {
|
|
125
|
+
try {
|
|
126
|
+
const store = JSON.parse(readFileSync(firebaseToolsConfigstorePath(env), 'utf8')) as {
|
|
127
|
+
tokens?: { access_token?: unknown; expires_at?: unknown };
|
|
128
|
+
};
|
|
129
|
+
const token = store.tokens?.access_token;
|
|
130
|
+
const expiresAt = store.tokens?.expires_at;
|
|
131
|
+
if (typeof token !== 'string' || token === '') return undefined;
|
|
132
|
+
if (typeof expiresAt !== 'number' || expiresAt - now < CLI_TOKEN_MARGIN_MS) return undefined;
|
|
133
|
+
return token;
|
|
134
|
+
} catch {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|