Skip to content

Add External Phone Provider OTP-delivery Azure Function sample (JavaScript, .NET, Python) - #1

Open
Hou (SciencePotato) wants to merge 4 commits into
mainfrom
add-cyot-sample
Open

Add External Phone Provider OTP-delivery Azure Function sample (JavaScript, .NET, Python)#1
Hou (SciencePotato) wants to merge 4 commits into
mainfrom
add-cyot-sample

Conversation

@SciencePotato

@SciencePotato Hou (SciencePotato) commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

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.

Hou Chi Chan 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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread docs/CONTRACT.md Outdated
Comment thread docs/local.settings.sample.json Outdated
Comment thread javascript/src/functions/security.js Outdated
Comment thread python/src/security.py
Comment thread python/src/dispatch.py Outdated
Hou Chi Chan 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.
@SciencePotato Hou (SciencePotato) changed the title Add CYOT OTP-delivery Azure Function sample (JavaScript, .NET, Python) Add External Phone Provider OTP-delivery Azure Function sample (JavaScript, .NET, Python) Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants