Add External Phone Provider OTP-delivery Azure Function sample (JavaScript, .NET, Python) - #1
Open
Hou (SciencePotato) wants to merge 4 commits into
Open
Add External Phone Provider OTP-delivery Azure Function sample (JavaScript, .NET, Python)#1Hou (SciencePotato) wants to merge 4 commits into
Hou (SciencePotato) wants to merge 4 commits into
Conversation
added 2 commits
August 17, 2026 11:38
Provider-agnostic OTP-delivery Azure Function in three languages (Node v4, .NET 8 isolated, Python v2) sharing one contract (docs/CONTRACT.md): one dispatch engine + drop-in provider adapters (Infobip, Telesign, Soprano, Sinch), Entra JWT validation, JWE delivery context (RSA-OAEP-256 + A256GCM) with structural/size validation, Key Vault secrets via managed identity, 202 Accepted with verbatim nonce echo, and conformance tests.
Drop scripts/ (JWE key provisioning + nonce-echo test client) and the scripts-specific .gitignore entry.
There was a problem hiding this comment.
Pull request overview
Adds a provider-agnostic CYOT OTP-delivery Azure Function sample implemented in JavaScript (Node.js), C# (.NET 8 isolated), and Python (Functions v2 model), all conforming to a shared contract and shipped with conformance tests and CI.
Changes:
- Introduces a shared contract + onboarding docs and wires CI to run conformance tests in all three languages.
- Implements dispatch engines + provider adapters (Infobip, Telesign, Soprano, Sinch) with Key Vault (managed identity) secret resolution and fail-closed outcome mapping.
- Adds envelope parsing + JWE decryption + optional Entra JWT validation, plus language-specific HTTP triggers for
POST /api/SendOtp.
Reviewed changes
Copilot reviewed 63 out of 67 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Repo entrypoint: links to implementations + contract/onboarding docs. |
| python/tests/test_engine.py | Python engine conformance tests (dispatch pipeline + fail-closed mapping). |
| python/tests/test_cyot.py | Python envelope + JWE round-trip + mapping tests. |
| python/tests/test_contract.py | Python pure-contract tests (outcome/status mapping, provider request shaping). |
| python/src/security.py | Python Entra JWT validation (REQUIRE_AUTH gating). |
| python/src/secrets.py | Python Key Vault secret resolver w/ managed identity + short TTL cache. |
| python/src/registry.py | Python provider adapter registry + DEFAULT_PROVIDER resolution. |
| python/src/providers/telesign.py | Python Telesign adapter (build/parse + mapping). |
| python/src/providers/soprano.py | Python Soprano adapter (build/parse + mapping). |
| python/src/providers/sinch.py | Python Sinch adapter (build/parse + mapping). |
| python/src/providers/infobip.py | Python Infobip adapter (build/parse + mapping). |
| python/src/providers/init.py | Python providers package marker. |
| python/src/outcome.py | Python provider-status → outcome → HTTP status mapping (fail-closed). |
| python/src/models.py | Python shared contract models/constants (DispatchRequest + outcomes). |
| python/src/dispatch.py | Python dispatch engine: resolve → creds → endpoint → send → map outcome/status. |
| python/src/cyot.py | Python envelope parsing + JWE validation/decrypt + mapping to dispatch shape. |
| python/src/init.py | Python src package marker. |
| python/requirements.txt | Python dependency ranges for Functions runtime + crypto/JWT + Azure SDKs. |
| python/README.md | Python implementation documentation + build/test/run/deploy instructions. |
| python/host.json | Python Functions host config (AI sampling + extension bundle). |
| python/function_app.py | Python HTTP trigger for SendOtp (auth/envelope/JWE/dispatch + nonce echo). |
| javascript/test/sendotp.test.js | JS SendOtp handler tests: validation, decrypt, evaluation, auth rejection. |
| javascript/test/security.test.js | JS privacy test: ensure OTP + phone never in logs/response body. |
| javascript/test/dispatch.test.js | JS dispatch integration tests: providers, mapping, shutter, fail-closed. |
| javascript/test/auth.test.js | JS token validation unit tests (REQUIRE_AUTH behavior). |
| javascript/src/functions/SendOtp.js | JS SendOtp HTTP handler (auth/envelope/JWE/dispatch + nonce echo). |
| javascript/src/functions/security.js | JS Entra JWT validation (JWKS + issuer/audience). |
| javascript/src/functions/providers/telesign.js | JS Telesign adapter (manifest/build/parse). |
| javascript/src/functions/providers/soprano.js | JS Soprano adapter (manifest/build/parse). |
| javascript/src/functions/providers/sinch.js | JS Sinch adapter (manifest/build/parse). |
| javascript/src/functions/providers/infobip.js | JS Infobip adapter (manifest/build/parse). |
| javascript/src/functions/dispatch.js | JS dispatch engine: provider registry, Key Vault secrets, send + mapping. |
| javascript/src/functions/cyot.js | JS envelope parsing + JWE validation/decrypt + mapping to dispatch shape. |
| javascript/README.md | JS implementation documentation + configuration catalog and examples. |
| javascript/package.json | JS dependencies + test/start scripts. |
| javascript/package-lock.json | JS dependency lockfile for reproducible installs in CI. |
| javascript/host.json | JS Functions host config (AI sampling + extension bundle). |
| dotnet/tests/EnvelopeTests.cs | .NET envelope parsing + JWE round-trip tests. |
| dotnet/tests/EngineTests.cs | .NET engine conformance tests (dispatch pipeline + privacy). |
| dotnet/tests/Cyot.Otp.Tests.csproj | .NET test project config + references (compiles Src directly). |
| dotnet/tests/ContractTests.cs | .NET pure-contract tests (mapping + request shaping + registry). |
| dotnet/Src/TokenValidator.cs | .NET Entra JWT validation w/ cached OIDC config/JWKS. |
| dotnet/Src/SecretResolver.cs | .NET Key Vault secret resolver w/ managed identity + TTL cache. |
| dotnet/Src/Providers/TelesignProvider.cs | .NET Telesign adapter (build/parse + mapping). |
| dotnet/Src/Providers/SopranoProvider.cs | .NET Soprano adapter (build/parse + mapping). |
| dotnet/Src/Providers/SinchProvider.cs | .NET Sinch adapter (build/parse + mapping). |
| dotnet/Src/Providers/InfobipProvider.cs | .NET Infobip adapter (build/parse + mapping). |
| dotnet/Src/ProviderRegistry.cs | .NET provider registry + DEFAULT_PROVIDER resolution. |
| dotnet/Src/OutcomeMapper.cs | .NET provider-status → outcome → HTTP status mapping (fail-closed). |
| dotnet/Src/Models.cs | .NET shared contract records/interfaces (DispatchRequest, manifests, etc.). |
| dotnet/Src/ISecretResolver.cs | .NET abstraction seam for secrets (testability). |
| dotnet/Src/IProviderAdapter.cs | .NET adapter interface (manifest + build/parse). |
| dotnet/Src/DispatchEngine.cs | .NET dispatch engine: resolve → creds → endpoint → send → map outcome/status. |
| dotnet/Src/DeliveryContext.cs | .NET JWE decryptor + key-provider contract + Key Vault key provider. |
| dotnet/Src/CyotEnvelope.cs | .NET envelope record + parser/validation. |
| dotnet/README.md | .NET implementation documentation + build/test/run/deploy instructions. |
| dotnet/Properties/launchSettings.json | .NET local launch profile. |
| dotnet/Program.cs | .NET Functions host startup + DI registration for engine/providers. |
| dotnet/host.json | .NET Functions host config (OpenTelemetry telemetryMode). |
| dotnet/Functions/SendOtp.cs | .NET SendOtp HTTP trigger (auth/envelope/JWE/dispatch + nonce echo). |
| dotnet/dotnet.csproj | .NET Functions project file + package refs. |
| dotnet/.gitignore | .NET-specific ignore rules (local.settings.json, VS artifacts, etc.). |
| docs/ONBOARDING.md | High-level onboarding guide (shared across languages). |
| docs/local.settings.sample.json | Reference app settings template for local/azure configuration. |
| docs/CONTRACT.md | Shared language-agnostic contract + required behaviors/test scenarios. |
| .gitignore | Repo-wide ignores (local.settings.json, keys, build artifacts). |
| .github/workflows/ci.yml | CI workflow: runs JS/node:test, .NET xUnit, Python pytest. |
Files not reviewed (1)
- javascript/package-lock.json: Generated file
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
added 2 commits
August 18, 2026 14:44
- CONTRACT: evaluation scenario shows 202 (matches implementations) - Sample settings: include 'python' worker runtime - JS token validation: accept both v2 and v1 (sts.windows.net) issuers, like .NET/Python - Python: cache PyJWKClient per tenant (avoid per-request JWKS fetch) - Python: fall back to default when ENDPOINT_TIMEOUT_MS is non-integer
CYOT remains the internal code name and is unchanged in wire-level identifiers (type names, CYOT_JWE_PRIVATE_KEY_PEM, SAS User-Agent); CONTRACT.md now notes this explicitly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contributes the provider-agnostic External Phone Provider OTP-delivery Azure Function sample in three languages (Node v4, .NET 8 isolated, Python v2) against one shared contract (docs/CONTRACT.md). One dispatch engine + drop-in provider adapters (Infobip, Telesign, Soprano, Sinch); Entra JWT validation (REQUIRE_AUTH); JWE delivery context pinned to RSA-OAEP-256 + A256GCM with 5-segment/size validation; provider secrets in Key Vault via managed identity; 202 Accepted with verbatim nonce echo; fail-closed outcome-to-HTTP mapping; xUnit/node:test/pytest conformance suites. Verified end-to-end against a live Azure deployment across all three languages and all provisioned providers.
Note: 'CYOT' (Choose Your Own Telecom) remains the internal code name and is retained only in wire-level identifiers (type names, the CYOT_JWE_PRIVATE_KEY_PEM app setting, and the SAS User-Agent); customer-facing docs use 'External Phone Provider'.
See docs/ONBOARDING.md to get started.