Skip to content

Commit d7598cc

Browse files
authored
Merge branch 'main' into feature/soprano-voice-improvements
2 parents d26fec3 + 04503a8 commit d7598cc

13 files changed

Lines changed: 280 additions & 174 deletions

File tree

‎.github/workflows/packages.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,5 @@ jobs:
145145
tag="epp-packages-${RUN_NUMBER}-${RUN_ATTEMPT}"
146146
gh release create "$tag" artifacts/*.zip artifacts/SHA256SUMS.txt \
147147
--target "$COMMIT_SHA" --title "EPP Function ZIPs ${RUN_NUMBER}.${RUN_ATTEMPT}" \
148+
--latest \
148149
--notes "Packaged and tested from commit ${COMMIT_SHA}. Download one language ZIP and verify it against SHA256SUMS.txt. JavaScript includes production dependencies. .NET contains project and C# source only: extract and build/publish the project before deployment. Python is a source ZIP requiring Azure remote build on Linux. Neither source ZIP is a direct run-from-package artifact. Configure runtime, app settings, Key Vault access, and Easy Auth separately. No cloud deployment or live provider verification is performed."

‎README.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ Easy Auth. The home tenant remains allowed by Entra. Policy activation remains m
3737

3838
## Download a Function ZIP
3939

40-
Download the preview ZIP for your chosen language:
40+
Download the latest successful CI ZIP for your chosen language:
4141

4242
| Language | Download | Contents |
4343
|---|---|---|
44-
| JavaScript | [epp-javascript.zip](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/download/epp-guided-setup-preview-20260915/epp-javascript.zip) | Application and production dependencies |
45-
| .NET | [epp-dotnet-source.zip](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/download/epp-guided-setup-preview-20260915/epp-dotnet-source.zip) | C# Function source and project file; build/publish before deployment |
46-
| Python | [epp-python-source.zip](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/download/epp-guided-setup-preview-20260915/epp-python-source.zip) | Source for Azure remote build on Linux |
44+
| JavaScript | [epp-javascript.zip](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/latest/download/epp-javascript.zip) | Application and production dependencies |
45+
| .NET | [epp-dotnet-source.zip](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/latest/download/epp-dotnet-source.zip) | C# Function source and project file; build/publish before deployment |
46+
| Python | [epp-python-source.zip](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/latest/download/epp-python-source.zip) | Source for Azure remote build on Linux |
4747

4848
Customers do not need PowerShell or a local build toolchain to download these files. Verify downloads
4949
against the corresponding release's `SHA256SUMS.txt`. Configure the target Function App's runtime, app settings,
@@ -52,14 +52,14 @@ project; Python requires remote build to install dependencies. Neither source ZI
5252
as a run-from-package artifact. GitHub's **Code > Download ZIP**
5353
is the whole source repository, not a Function deployment package.
5454

55-
After the packaging workflow is merged, each successful `main` build tests all three implementations,
56-
builds and inspects the ZIPs, and publishes a new versioned release. Get those builds from
55+
Each successful `main` build tests all three implementations, builds and inspects the ZIPs, and
56+
publishes a new versioned release marked as the latest release.
57+
The direct links above and guided setup therefore track the newest successful CI package build. Get builds from
5758
[Latest release](https://github.com/Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample/releases/latest).
5859
Older releases remain available; existing assets are not overwritten. Pull requests build downloadable
5960
workflow artifacts only and cannot publish releases. GitHub sign-in may be required for workflow
6061
artifacts, but public release downloads do not require a local build. Packaging does not deploy or
61-
verify live provider delivery. The current preview is built from the packaging branch, not a merged
62-
release of the separate provider feature branches.
62+
verify live provider delivery.
6363

6464
## Build ZIPs Locally
6565

‎docs/ONBOARDING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Use [CONTRACT.md](CONTRACT.md) for the full request contract and production limi
6262
| `EPP_PROVIDER_APP_ID`, `EPP_PROVIDER_SCOPE` | Soprano API application ID and the exact selected scope, including `/.default`. These are not the calling application's ID. Leave blank for API-key providers. |
6363
| `EPP_OUTBOUND_CLIENT_ID` | Existing calling application's Application (client) ID used during setup, not its Object ID or Soprano's API ID. |
6464
| `EPP_OUTBOUND_MI_CLIENT_ID` | Setup-created outbound user-assigned identity's Client ID, not its principal/Object ID. |
65-
| `EPP_PROVIDER_TIMEOUT_MS`, `EPP_PROVIDER_RETRY_INTERVAL_MS`, `EPP_PROVIDER_TEST_CONFIGURATION` | Selected profile values, as strings. Retry interval and test-configuration metadata do not enable runtime retries or shutter mode. |
65+
| `EPP_PROVIDER_TIMEOUT_MS`, `EPP_PROVIDER_RETRY_INTERVAL_MS` | Selected profile values, as strings. The retry interval does not enable runtime retries or shutter mode. |
6666
| `KEY_VAULT_URL` | Setup-created or explicitly selected credential vault URL, not a secret value. |
6767

6868
The outbound IDs are used only for Soprano OAuth; leave them blank for local API-key-only

‎docs/local.settings.sample.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"EPP_PROVIDER_SCOPE": "",
1717
"EPP_PROVIDER_TIMEOUT_MS": "1500",
1818
"EPP_PROVIDER_RETRY_INTERVAL_MS": "30000",
19-
"EPP_PROVIDER_TEST_CONFIGURATION": "false",
2019

2120
"EPP_OUTBOUND_CLIENT_ID": "",
2221
"EPP_OUTBOUND_MI_CLIENT_ID": "",

‎setup/EPP-Setup.psd1‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@{
22
PackageName = 'EPP endpoint deployment'
3-
PackageVersion = '0.3.0'
3+
PackageVersion = '0.3.1'
44
EntryPoint = 'Setup-Epp.ps1'
55
MinimumPowerShellVersion = '7.0'
66
Support = @('support/Epp.Setup.psm1', 'support/Epp.Packages.ps1')

‎setup/Setup-Epp.ps1‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
No Azure resources are changed until you approve the complete plan.
1010
.PARAMETER SourceRepository
1111
Public GitHub owner/repository containing the setup files. Use with SourceRef to test a fork.
12+
.PARAMETER PackageReleaseTag
13+
Optional stable epp-packages release tag. By default, setup uses the latest stable CI package release.
1214
.PARAMETER InstallPrerequisites
1315
Install missing Microsoft Graph modules and the Azure CLI Bicep component after explicit opt-in.
1416
.PARAMETER ForceAuthentication
@@ -27,13 +29,13 @@ param(
2729
[string] $Provider,
2830
[string] $Channel,
2931
[string] $EndpointRegion,
30-
[string] $ProviderAccountName,
3132
[string] $ResourcePrefix,
3233
[string] $Language,
3334
[string] $OutputDirectory = (Join-Path $PSScriptRoot 'epp-output'),
3435
[ValidatePattern('^[A-Za-z0-9][A-Za-z0-9-]*/[A-Za-z0-9][A-Za-z0-9_.-]*$')]
3536
[string] $SourceRepository = 'Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample',
3637
[string] $SourceRef = 'main',
38+
[string] $PackageReleaseTag,
3739
[switch] $NonInteractive,
3840
[switch] $InstallPrerequisites,
3941
[switch] $ForceAuthentication,

‎setup/docs/README.md‎

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,22 @@ The customer does not clone this repository or download Bicep/support scripts se
88

99
## Availability
1010

11-
Choose **JavaScript, .NET, or Python**, then **Telesign or Soprano**, **SMS or voice**, and a
12-
**Global or EU endpoint**. The private test branch uses its matching fork preview release so the
13-
package and provider-authentication contract stay in sync. There is no package URL or checksum to
14-
enter. Setup verifies `SHA256SUMS.txt` automatically and performs the required build and publication
15-
for the selected language.
16-
17-
Provider profiles contain complete channel/region route objects. Unknown values use **explicit dummy
18-
test values**, not a separate placeholder list or empty fields that block setup. They are written
19-
into the Function App's **actual environment settings** after approval. Telesign's supplied route
20-
URLs, tenant, and timings are preserved, while its zero application IDs remain test-labelled.
21-
Soprano contains its provider tenant, production Global/EU routes, API application ID, scope, and
22-
timing values.
23-
The plan and saved summary identify test configuration. Deployment does not make these values
24-
working endpoints or credentials. The provider files contain the complete deployment contract.
25-
26-
The default download URLs below become usable when this change is published upstream. Before merging,
27-
test from a published public fork using `-SourceRepository <owner/repository>` and
11+
Choose **SMS or voice**, a **Global or EU tenant scope**, **Telesign or Soprano**, and an
12+
Azure Function **platform**: Node.js, .NET, or Python. By default, setup resolves the source repository's latest stable
13+
`epp-packages-*` release produced by CI. A private test branch can use its matching fork release.
14+
There is no package URL or checksum to enter. Setup verifies `SHA256SUMS.txt` automatically and
15+
performs the required build and publication for the selected language.
16+
17+
Provider profiles contain complete channel/region route objects. Telesign contains its supplied
18+
route URLs, tenant, authentication, and timings. Soprano contains its provider tenant, Global/EU
19+
routes, API application ID, scope, authentication, and timings. The provider files contain the
20+
complete deployment contract.
21+
22+
To test unpublished upstream changes, publish them to a public fork with a matching stable package
23+
release, then use `-SourceRepository <owner/repository>` and
2824
`-SourceRef <branch-or-full-commit-sha>`. Both options must identify the same source as the downloaded
29-
launcher. Unpublished worktree changes are not downloadable from GitHub.
25+
launcher. Use `-PackageReleaseTag` if the fork contains more than one stable package release.
26+
Unpublished worktree changes are not downloadable from GitHub.
3027

3128
## Step 1 - manually create the application
3229

@@ -129,17 +126,20 @@ Force explicit account selection when testing on a shared or multi-account compu
129126
The flow is:
130127

131128
1. **Collect missing customer inputs:** tenant, subscription, existing application client ID, Azure
132-
region, and provider account/sender name. Supplied values
133-
are reused without prompts. Credentials are never requested as ordinary string parameters.
134-
2. **Choose one language**. Setup looks up its GitHub release and checksum file in
135-
`packages/catalog.json`; there are no `PackageUrl` or `PackageSha256` inputs.
136-
3. **Choose a provider**, then **SMS or voice**, then **Global or EU endpoint**. Setup downloads the
137-
provider JSON and resolves one complete route containing endpoint, authentication, app-ID/scope
129+
region, and resource prefix. Supplied values are reused without prompts. Credentials are never
130+
requested as ordinary string parameters.
131+
2. **Choose SMS or voice**, then the **Global or EU tenant scope**.
132+
3. **Choose a provider**, then an Azure Function **platform**: Node.js, .NET, or Python. Setup downloads the provider JSON,
133+
resolves one complete route containing endpoint, authentication, app-ID/scope
138134
when applicable, timeout, and retry interval. Explicit test values are allowed, shown as test
139-
configuration, and passed to Azure settings. Malformed or disabled profiles still fail before
140-
resource creation.
141-
4. **Enter a resource prefix**, such as `contoso`: 2-8 lowercase letters/digits, starting with a
142-
letter. Every top-level resource name then adds the meaningful `epp` marker, for example
135+
configuration, and passed to Azure settings. It also resolves the latest stable CI package
136+
release and looks up the language asset name in `packages/catalog.json`; there are no
137+
`PackageUrl` or `PackageSha256` inputs. Use
138+
`-PackageReleaseTag epp-packages-<run>-<attempt>` to pin a previous CI release. Malformed or
139+
disabled profiles still fail before resource creation.
140+
4. **Enter a resource prefix**, such as `contoso`. All resources created by the script start with
141+
this prefix. Use 2-8 lowercase letters or digits, starting with a letter. Every top-level
142+
resource name then adds the meaningful `epp` marker, for example
143143
`contoso-epp-rg-<suffix>`. A deterministic suffix derived from the
144144
subscription, application ID, and prefix reduces global-name collisions. Reruns use the same names.
145145
5. **Check prerequisites and sign in.** Missing Graph modules or Bicep can be installed after a
@@ -197,9 +197,7 @@ explicitly rather than hidden.
197197

198198
The public certificate and a timestamped identifier
199199
summary are saved to `epp-output` beside the downloaded script, or to `-OutputDirectory`.
200-
Private keys remain in the user's certificate store and Key Vault, not in that summary. With dummy
201-
profiles, `EPP_PROVIDER_TEST_CONFIGURATION=true` is stored alongside the real environment settings.
202-
This is a label, not a replacement for caller authentication or a guarantee of provider connectivity.
200+
Private keys remain in the user's certificate store and Key Vault, not in that summary.
203201

204202
For unattended runs, supply every input, authenticate both clients first, and explicitly authorize
205203
the whole displayed plan with **both** `-NonInteractive -ApproveDeployment`. `-NonInteractive`
@@ -210,35 +208,37 @@ alone never approves changes. There is no `-Stage`, `-Resume`, `-ConfigPath`, or
210208
`-SourceRepository` defaults to `Azure-Samples/ExternalPhoneProvider-AzureFunction-Sample`.
211209
The small entry point resolves `-SourceRef` (default `main`) to a single commit in that repository. All supporting
212210
PowerShell, Bicep, the catalog, and the selected provider profile are downloaded from that commit.
213-
Use a reviewed full commit SHA for repeatable deployments. Provider JSON selects data only; it
214-
cannot redirect execution to another script. Download failures stop setup, and temporary downloads
215-
are removed on completion or failure. Select only a repository whose code you trust: its supporting
211+
The package catalog supplies asset names, while setup resolves the latest stable `epp-packages-*`
212+
release from the same repository and verifies the selected asset against that release's
213+
`SHA256SUMS.txt`. The plan and saved summary record the concrete versioned URL and hashes.
214+
For a fully repeatable deployment, use both a reviewed full commit SHA and
215+
`-PackageReleaseTag epp-packages-<run>-<attempt>`. Provider JSON selects data only; it cannot
216+
redirect execution to another script. Download failures stop setup, and temporary downloads are
217+
removed on completion or failure. Select only a repository whose code you trust: its supporting
216218
PowerShell is executed locally.
217219

218220
## Step 3 - manually validate and activate policy
219221

220222
1. Save the Step 2 summary and confirm its tenant, application client ID, endpoint URL, encryption
221223
key ID, and certificate with the EPP onboarding owner. **Replace all test provider values** and
222224
provision the adapter-named API credentials in Key Vault. Verify the package's channel routing
223-
and retry behavior; the tenant/scope metadata and test label do not enable unsupported behavior.
225+
and retry behavior.
224226
2. Validate the deployed endpoint with synthetic, non-delivering evaluation requests first.
225227
Missing/invalid credentials and unauthorized callers must be rejected by Easy Auth. An admitted
226228
caller's valid encrypted request must return the matching nonce. Then verify live SMS/voice
227229
provider acceptance and handset delivery through the supported test procedure. Never put
228230
phone numbers, messages, tokens, private keys, or nonce values in shared logs.
229231
3. An **Authentication Policy Administrator**, using the approved Microsoft Graph tool and delegated
230-
`Policy.ReadWrite.AuthenticationMethod`, must verify that the tenant's currently supported EPP
231-
contract is available. For the preview contract formerly handled by Step 3, inspect
232-
`https://graph.microsoft.com/beta/$metadata` for `authenticationMethodsPolicy.cyot` and its
233-
`endpoint`, `appId`, and `migrated` fields. **If absent or different, stop and obtain the supported
234-
onboarding procedure from Microsoft; do not send a guessed PATCH or enable a different method.**
235-
4. Read `https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy` using that supported
236-
contract, save the existing `cyot` value with tenant ID and timestamp, and independently approve
237-
the migration choice. `migrated` is a routing decision, not a script default.
238-
5. Re-read immediately before a manual change, stop if the policy changed, and use `If-Match` when
239-
an ETag is available. Patch **only** the `cyot` property with the tested endpoint, the same
240-
application client ID, and the deliberately chosen migration Boolean. Read it back and compare
241-
before considering activation complete.
232+
`Policy.ReadWrite.AuthenticationMethod`, must read the selected channel configuration:
233+
`https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/Sms`
234+
for SMS or the same path ending in `/Voice` for voice. If the selected configuration or its
235+
`url` and `appId` properties are unavailable, stop and obtain the supported onboarding procedure
236+
from Microsoft rather than sending a guessed update.
237+
4. Save the existing channel configuration with the tenant ID and timestamp. Re-read it immediately
238+
before a manual change, stop if it changed, and use `If-Match` when an ETag is available.
239+
5. Update `url` with the highlighted Function endpoint and `appId` with the highlighted endpoint
240+
application client ID printed by setup. Preserve all other properties, then read the configuration
241+
back and compare those values before considering activation complete.
242242

243243
Policy activation, policy backups, and policy rollback are administrator-owned manual operations.
244244
No policy API is called by the setup package. For rollback, restore only the reviewed prior EPP

‎setup/docs/Troubleshooting.md‎

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,13 @@ the intended `-SourceRepository` and `-SourceRef`. The current version asks for
6868
and reads its package URL and published checksum automatically. Remove old package URL/hash
6969
arguments from saved commands.
7070

71-
## Provider settings are dummy values
72-
73-
Telesign remains explicitly labelled with `deployment.testConfiguration: true` because its route
74-
application IDs are still zero GUIDs. The selected values are written into the actual Function App
75-
environment with `EPP_PROVIDER_TEST_CONFIGURATION=true`. Soprano now has provider-supplied tenant,
76-
endpoint, application ID, scope, and timing values and is not labelled as test configuration.
77-
78-
The script can deploy code with these values, but dummy routes cannot deliver real messages.
79-
Update the provider-owned profile before live use. Telesign requires its API-key secrets in Key
80-
Vault. Soprano uses the selected OAuth tenant/scope/app ID and outbound managed-identity federation;
81-
provider consent and API roles remain external onboarding steps.
82-
8371
## A checksum or package download fails
8472

85-
Each language entry points to a versioned GitHub ZIP and the same release's `SHA256SUMS.txt`.
86-
The file must contain exactly one valid entry for that asset. Missing, duplicate, malformed, or
87-
mismatched checksums fail closed; there is no manual-hash or skip-verification workaround.
88-
Verify the catalog's links and your access to GitHub/release assets.
73+
Setup resolves the latest stable `epp-packages-*` CI release by default, then downloads the selected
74+
catalog asset and that release's `SHA256SUMS.txt`. Use `-PackageReleaseTag` when reproducing a
75+
specific release. The checksum file must contain exactly one valid entry for that asset. Missing,
76+
duplicate, malformed, or mismatched checksums fail closed; there is no manual-hash or
77+
skip-verification workaround. Verify the release assets and your access to GitHub.
8978

9079
Supporting tools, Bicep, catalogs, and provider JSON all come from the commit selected at startup.
9180
For a public-fork branch, pass both source options. A full commit SHA avoids branch-resolution

0 commit comments

Comments
 (0)