@serve.zone/interfaces 32.22.0 → 32.24.0
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/changelog.md +76 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/data/corestorelegacyadoption.d.ts +182 -0
- package/dist_ts/data/corestorelegacyadoption.js +292 -0
- package/dist_ts/data/index.d.ts +2 -0
- package/dist_ts/data/index.js +3 -1
- package/dist_ts/data/networkprotection.d.ts +13 -0
- package/dist_ts/data/networkprotection.js +8 -2
- package/dist_ts/data/runtimelocalstorageclaim.d.ts +73 -10
- package/dist_ts/data/runtimelocalstorageclaim.js +89 -2
- package/dist_ts/data/service.d.ts +15 -1
- package/dist_ts/data/service.js +1 -1
- package/dist_ts/data/serviceruntime.d.ts +8 -3
- package/dist_ts/data/serviceruntime.js +3 -2
- package/dist_ts/data/servicevolumeinitialization.d.ts +91 -0
- package/dist_ts/data/servicevolumeinitialization.js +93 -0
- package/dist_ts/platform/types.d.ts +45 -0
- package/dist_ts/platform/types.js +27 -2
- package/dist_ts/requests/corestore.d.ts +60 -0
- package/dist_ts/requests/corestore.js +1 -1
- package/dist_ts/requests/platform.d.ts +6 -1
- package/dist_ts/requests/service.d.ts +23 -0
- package/package.json +1 -1
- package/readme.md +186 -16
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/data/corestorelegacyadoption.ts +481 -0
- package/ts/data/index.ts +2 -0
- package/ts/data/networkprotection.ts +20 -1
- package/ts/data/runtimelocalstorageclaim.ts +169 -10
- package/ts/data/service.ts +16 -0
- package/ts/data/serviceruntime.ts +8 -2
- package/ts/data/servicevolumeinitialization.ts +159 -0
- package/ts/platform/types.ts +75 -0
- package/ts/requests/corestore.ts +79 -0
- package/ts/requests/platform.ts +6 -0
- package/ts/requests/service.ts +28 -0
package/readme.md
CHANGED
|
@@ -1418,17 +1418,22 @@ phase, settlement, release or authority booleans or evidence.
|
|
|
1418
1418
|
on one spec revision, and each reason belongs to exactly one state. `converged` and `converging`
|
|
1419
1419
|
carry `reason: null`. `waiting` carries a `TServiceRuntimeWaitingReason`: `node-network-pending`,
|
|
1420
1420
|
`conflict`, `failure-backoff`, `storage-import-pending` (an `import` local storage claim whose bytes
|
|
1421
|
-
have not arrived on its node)
|
|
1422
|
-
binding of the service yet)
|
|
1421
|
+
have not arrived on its node), `bindings-pending` (the secret manifest does not cover every enabled
|
|
1422
|
+
binding of the service yet) or `legacy-adoption-pending` (a Corestore binding of the service waits for
|
|
1423
|
+
the offline adoption of its legacy resource, see
|
|
1424
|
+
[Corestore Legacy Resource Adoption](#corestore-legacy-resource-adoption)). `refused` carries a
|
|
1425
|
+
`TServiceRuntimeRefusal`:
|
|
1423
1426
|
`cluster-runtime-missing`, `organization-missing`, `image-plan-missing`, `platform-unsupported`,
|
|
1424
1427
|
`secrets-unsupported`, `volumes-unsupported`, `port-protocol-unsupported`, `ports-too-many`,
|
|
1425
1428
|
`readiness-target-undeclared`, `environment-too-large`, `no-eligible-node`, `replica-limit`,
|
|
1426
1429
|
`node-authority-unsupported`, `network-policy-missing`, `network-policy-mismatch`,
|
|
1427
1430
|
`network-workload-pool-missing`, `network-workload-pool-exhausted`, `volume-driver-unsupported`,
|
|
1428
|
-
`volume-options-unsupported`, `volume-shared-unsupported
|
|
1429
|
-
volume
|
|
1430
|
-
|
|
1431
|
-
|
|
1431
|
+
`volume-options-unsupported`, `volume-shared-unsupported`, `volume-placement-unsupported`,
|
|
1432
|
+
`volume-initialization-unknown` or `volume-ownership-unknown`. The first four volume refusals name
|
|
1433
|
+
what a local storage claim cannot express: a volume driver other than a node-local directory, driver
|
|
1434
|
+
or mount options, one volume mounted by more than one replica or service, and a placement that does
|
|
1435
|
+
not pin each volume to one node. The last two name what Cloudly will not guess, see
|
|
1436
|
+
[Service Volume Initialization](#service-volume-initialization). `ports-too-many` is a service declaring more target ports than the
|
|
1432
1437
|
`runtimeConfigContract.maximumTargetPorts` (64) a config carries, where `port-protocol-unsupported`
|
|
1433
1438
|
is about one port's protocol; `node-authority-unsupported` is a node whose session resolved fewer
|
|
1434
1439
|
workload authorities than the spec needs, refused at the admit step rather than handed to a node
|
|
@@ -1440,6 +1445,52 @@ is `network-policy-missing`, and a disagreement with the requested egress or pla
|
|
|
1440
1445
|
retires running slots.
|
|
1441
1446
|
`snapshotServiceRuntimeStatus` enforces the pairing.
|
|
1442
1447
|
|
|
1448
|
+
### Service Volume Initialization
|
|
1449
|
+
|
|
1450
|
+
A local storage claim has to say how its volume starts: `empty` with an owner and mode, or `import`
|
|
1451
|
+
of bytes that already exist. `IServiceVolume.initialization` (`TServiceVolumeInitialization`) is
|
|
1452
|
+
where the service states it, per volume, beside the mount path it belongs to:
|
|
1453
|
+
|
|
1454
|
+
- `{ kind: 'empty', ownership }` creates an empty root. `ownership` is
|
|
1455
|
+
`{ kind: 'explicit', uid, gid, mode }`, or `{ kind: 'run-as', mode }`, which takes the owner from
|
|
1456
|
+
the runtime spec's `profile.runAs`. The mode is always stated; it holds directory permission bits
|
|
1457
|
+
only (`serviceVolumeInitializationContract.directoryModeBits`, `0o3777`, setuid refused).
|
|
1458
|
+
- `{ kind: 'import', source: { kind: 'docker-volume', volumeName } }` waits for the bytes of an
|
|
1459
|
+
existing Docker volume on the claim node's host, named exactly as Docker lists it (a
|
|
1460
|
+
Corestore-driver volume included). The operator copies that tree into the node's import directory;
|
|
1461
|
+
the claim does not carry the source, and the node never reads it.
|
|
1462
|
+
|
|
1463
|
+
It lives on the volume and not on the runtime spec because it is a fact about the volume's data,
|
|
1464
|
+
which the service declares, while the runtime spec carries only execution policy and is stored
|
|
1465
|
+
exactly, so a new member there would refuse every stored spec. It is server-managed:
|
|
1466
|
+
`setServiceVolumeInitialization { identity, serviceId, mountPath, expected, initialization }` is its
|
|
1467
|
+
only write. The volume is named by its exact mount path; `expected` is the value the caller read, or
|
|
1468
|
+
`null` for none, and any other stored value refuses. `createService` and `updateService` take volumes
|
|
1469
|
+
as `TServiceWritableVolume` (no `initialization`) and Cloudly refuses one that states it; a stored
|
|
1470
|
+
initialization stays with the volume of the same mount path and goes with the volume. Refusals travel
|
|
1471
|
+
as `IServiceVolumeInitializationErrorData { code, retryable: false }`: `volume-not-found`,
|
|
1472
|
+
`conflict`, `volume-initialization-invalid`, and `volume-initialization-bound`, a change while a
|
|
1473
|
+
bound local storage claim of the volume exists.
|
|
1474
|
+
|
|
1475
|
+
`validateServiceVolumeInitialization(value, path?)` names every reason a value is refused.
|
|
1476
|
+
`deriveServiceVolumeClaimInitialization(initialization, runAs)` is the one rule for the claim fields,
|
|
1477
|
+
and nothing in it is a default:
|
|
1478
|
+
|
|
1479
|
+
| Volume initialization | `runAs` | Claim `initialization` / `initialOwnership` |
|
|
1480
|
+
| --- | --- | --- |
|
|
1481
|
+
| absent | any | refused `volume-initialization-unknown` |
|
|
1482
|
+
| `empty`, `explicit` | any | `empty` / the stated `{ uid, gid, mode }` |
|
|
1483
|
+
| `empty`, `run-as` | `{ user, group }` | `empty` / `{ uid: user, gid: group, mode }` |
|
|
1484
|
+
| `empty`, `run-as` | `null` | refused `volume-ownership-unknown` |
|
|
1485
|
+
| `import` | any | `import` / `null` |
|
|
1486
|
+
|
|
1487
|
+
An absent initialization is refused rather than created empty, because an empty volume in front of a
|
|
1488
|
+
service whose data sits in a legacy Docker volume would start that service without its data. A
|
|
1489
|
+
`run-as` ownership under `runAs: null` is refused because the image's own user is not a number
|
|
1490
|
+
Cloudly knows. The rule decides the first generation of a claim only: every later generation carries
|
|
1491
|
+
that claim's own initialization and ownership, whatever `runAs` says by then, since the node refuses
|
|
1492
|
+
a claim whose initial ownership changed.
|
|
1493
|
+
|
|
1443
1494
|
### Runtime Assignment Views
|
|
1444
1495
|
|
|
1445
1496
|
`data.IServiceRuntimeAssignmentView` is one replica slot's current assignment as an administrator
|
|
@@ -1933,25 +1984,64 @@ native fence.
|
|
|
1933
1984
|
|
|
1934
1985
|
### Runtime local storage claims
|
|
1935
1986
|
|
|
1936
|
-
`data.IRuntimeLocalStorageClaim` is a controller's authority for one retained
|
|
1937
|
-
one
|
|
1938
|
-
the claim revision (`id`, `generation`, `previous`), the organization, cluster, node,
|
|
1939
|
-
namespace, service and the service's own `volumeId`, and it states:
|
|
1940
|
-
|
|
1941
|
-
- `source
|
|
1942
|
-
|
|
1943
|
-
|
|
1987
|
+
`data.IRuntimeLocalStorageClaim` is a controller's authority for one retained volume of one service,
|
|
1988
|
+
mounted on one node. Cloudly and Onebox issue it alike (`controller.kind` is `cloudly` or `onebox`).
|
|
1989
|
+
It names the claim revision (`id`, `generation`, `previous`), the organization, cluster, node,
|
|
1990
|
+
runtime namespace, service and the service's own `volumeId`, and it states:
|
|
1991
|
+
|
|
1992
|
+
- `source` (`TRuntimeLocalStorageSource`), one of:
|
|
1993
|
+
- `{ kind: 'directory' }` (`TRuntimeLocalStorageDirectorySource`), a node-local directory the node
|
|
1994
|
+
derives from the claim's identity under a root only the node knows;
|
|
1995
|
+
- `{ kind: 'nfs', server, export, subPath, version }` (`TRuntimeLocalStorageNfsSource`), the
|
|
1996
|
+
directory `subPath` below the NFS export `server:export`;
|
|
1997
|
+
- `{ kind: 'smb', server, share, subPath, version, credential }` (`TRuntimeLocalStorageSmbSource`),
|
|
1998
|
+
the directory `subPath` below the SMB share `//server/share`. `credential` is an
|
|
1999
|
+
`IRuntimeAuthorityReference { id, generation, digest }` naming the credential the node
|
|
2000
|
+
authenticates with; the claim never carries a user name, password or domain, and the node
|
|
2001
|
+
resolves the material through the controller's secret delivery. NFS authenticates the node's
|
|
2002
|
+
host, so an `nfs` source names no credential;
|
|
1944
2003
|
- `initialization`: `empty` creates an empty root with `initialOwnership { uid, gid, mode }`, which
|
|
1945
2004
|
an `empty` claim must state, so a workload without `runAs` never meets a root-owned directory by
|
|
1946
2005
|
accident; `import` waits for the volume's bytes to be imported and states `initialOwnership: null`,
|
|
1947
2006
|
because an imported tree keeps its own ownership. `mode` holds directory permission bits only
|
|
1948
|
-
(`runtimeLocalStorageClaimContract.directoryModeBits`, `0o3777`; setuid is refused)
|
|
2007
|
+
(`runtimeLocalStorageClaimContract.directoryModeBits`, `0o3777`; setuid is refused). SMB carries no
|
|
2008
|
+
POSIX ownership, so the node presents an SMB volume with `initialOwnership`, and an `smb` claim is
|
|
2009
|
+
always `empty`;
|
|
1949
2010
|
- `mount { mountPath, readOnly }`, judged by the storage request's own mount path rule: canonical,
|
|
1950
2011
|
absolute, not `/`, and never overlapping `/run/secrets`;
|
|
1951
2012
|
- `accessMode: 'ReadWriteOnce'`, `reclaimPolicy: 'retain'`, and `lifecycle`: `bound` keeps the
|
|
1952
2013
|
volume, `purge` orders its bytes deleted and always follows a bound generation of the same claim.
|
|
1953
2014
|
|
|
1954
|
-
|
|
2015
|
+
A network source names the remote directory and nothing about how to mount it, so the node derives
|
|
2016
|
+
every mount parameter from these fields alone and a claim cannot smuggle an option in:
|
|
2017
|
+
|
|
2018
|
+
| Field | Rule |
|
|
2019
|
+
| --- | --- |
|
|
2020
|
+
| `server` | a lowercase fully qualified hostname of two or more labels whose last label is not numeric (a single label would resolve through each node's own search domains), or a canonical IP literal (a dotted quad without leading zeros, or RFC 5952 IPv6 without brackets or zone). No scheme, user info or port: the node connects to the protocol's standard port |
|
|
2021
|
+
| `export` | `/`, or `/` and canonical segments without a trailing slash |
|
|
2022
|
+
| `subPath` | `.` for the export or share itself, or canonical relative segments |
|
|
2023
|
+
| `share` | one segment of at most 80 characters, without `+`, `;`, `[` or `]` |
|
|
2024
|
+
| `version` | `nfs`: `3`, `4.0`, `4.1` or `4.2`; `smb`: `3.0`, `3.02` or `3.1.1` |
|
|
2025
|
+
|
|
2026
|
+
A segment is printable ASCII without a space, at most 255 characters, never `.` or `..`, and holds
|
|
2027
|
+
none of `"`, `*`, `,`, `/`, `:`, `<`, `=`, `>`, `?`, `\` or `|`: a comma or `=` would read as a mount
|
|
2028
|
+
option, and the rest have meaning in a mount source or an SMB name. `export` and `subPath` are at
|
|
2029
|
+
most 1024 characters. ASCII keeps one spelling per segment, but one remote directory can still be
|
|
2030
|
+
named several ways: a hostname and an address of the same server, a different `export`/`subPath`
|
|
2031
|
+
split, or a nested `subPath`. The contract cannot detect these aliases, so the controller must refuse
|
|
2032
|
+
overlapping bound claims itself. The versions are the kernel's own `vers=` spellings, and each pins one protocol version: a
|
|
2033
|
+
bare NFS `4` or SMB `3` negotiates one, which a claim that must mean the same mount on every node
|
|
2034
|
+
cannot allow. NFS version 2 and the SMB 1 and 2 dialects are refused; SMB 3 is the first dialect
|
|
2035
|
+
that encrypts. The bounds and version lists
|
|
2036
|
+
are `runtimeLocalStorageClaimContract.nfsVersions`, `smbVersions`, `maximumServerLength`,
|
|
2037
|
+
`maximumPathLength`, `maximumSegmentLength` and `maximumShareLength`.
|
|
2038
|
+
|
|
2039
|
+
`ReadWriteOnce` holds on the node that mounts the claim. A network directory is reachable from more
|
|
2040
|
+
than one node, so the controller issues at most one bound claim per remote directory; a node cannot
|
|
2041
|
+
see another node's mounts. A `purge` of a network claim deletes everything below `subPath`, the
|
|
2042
|
+
whole export or share for `.`.
|
|
2043
|
+
|
|
2044
|
+
The claim carries no host path, device, mount option or credential value.
|
|
1955
2045
|
`snapshotRuntimeLocalStorageClaim` makes a detached exact-schema snapshot,
|
|
1956
2046
|
`computeRuntimeLocalStorageClaimDigest` hashes it under `serve.zone/runtime-local-storage-claim`,
|
|
1957
2047
|
`validateRuntimeLocalStorageClaim` verifies the stated digest, and
|
|
@@ -2632,6 +2722,15 @@ from one that states a value, and nothing downstream defaults or infers one. Clo
|
|
|
2632
2722
|
the node stated and resolves it into the route table; the relay never substitutes an address of
|
|
2633
2723
|
its own.
|
|
2634
2724
|
|
|
2725
|
+
The same report carries the optional `hostAddresses`: every IPv4 address the node's host carries on
|
|
2726
|
+
interfaces the node does not manage itself, sorted as strings, unique, never empty when present, at
|
|
2727
|
+
most `runtimeNetworkProtectionContract.maximumHostAddresses` (32), each one admitted by
|
|
2728
|
+
`runtimeNodeUplinkAddress`. Workload bridges and the managed VPN interface are the node's own and
|
|
2729
|
+
are left out. Cloudly names a plan platform endpoint in that node's `hostPlatformEndpointIds` when
|
|
2730
|
+
the endpoint's address is one of them. A relay registration already tells Cloudly which host carries
|
|
2731
|
+
the relay listener and hub; `hostAddresses` is how a host without a relay, such as a node with a
|
|
2732
|
+
Corestore beside it on one machine, states the same. Absent states nothing and is never defaulted.
|
|
2733
|
+
|
|
2635
2734
|
Shared service port helpers are exported from `data` so Cloudly, App Store resolution, Coreflow, Coretraffic, Onebox, and dcrouter agree on the same normalization rules:
|
|
2636
2735
|
|
|
2637
2736
|
```typescript
|
|
@@ -3316,6 +3415,77 @@ recipient the relay enrolled with `beginSecretRecipientEnrollment` and
|
|
|
3316
3415
|
`completeSecretRecipientEnrollment` — see [Corestore Runtime Credentials](#corestore-runtime-credentials).
|
|
3317
3416
|
No credential travels in the cluster document, and none is read from the relay's environment.
|
|
3318
3417
|
|
|
3418
|
+
### Corestore Legacy Resource Adoption
|
|
3419
|
+
|
|
3420
|
+
A Corestore root converted from a release before 32 still holds the databases and buckets
|
|
3421
|
+
`/resources/provision` created, one per service and capability, in its manifest. Corestore refuses a
|
|
3422
|
+
credential binding beside such a resource until an operator authorizes that exact binding to adopt
|
|
3423
|
+
it, offline, with a plan file; a fresh binding would otherwise start from an empty database or bucket
|
|
3424
|
+
while the data stays behind. These contracts carry that flow across Corestore, the relay, Cloudly and
|
|
3425
|
+
Coreflow, all exported from `data` and `platform`:
|
|
3426
|
+
|
|
3427
|
+
1. **Inventory.** Corestore answers `GET /control/legacy-resources`
|
|
3428
|
+
(`corestoreLegacyAdoptionContract.inventoryPath`, bearer-authenticated like every control path)
|
|
3429
|
+
with `ICorestoreLegacyResourceInventory { services }`: every service, sorted by id, with one or
|
|
3430
|
+
two `TCorestoreLegacyResource` entries, `database` before `objectstorage`. A database is named by
|
|
3431
|
+
`databaseName`, a bucket by `bucketName` and `retention` (its `IObjectStorageRetentionIntent`, or
|
|
3432
|
+
`null`). Each carries its `adoption`: `{ state: 'unadopted', blocker }` or
|
|
3433
|
+
`{ state: 'authorized', bindingId }`. The blocker names what would stop the offline adoption,
|
|
3434
|
+
`null` when nothing would: `not-adoptable` (an allocation-managed database, another provider, a
|
|
3435
|
+
resource name that is not its database or bucket name, or a bucket name that is not a canonical S3
|
|
3436
|
+
name), `ordinary-credentials-rotated`, `owned-by-binding` or `fence-lineage-conflict` (the
|
|
3437
|
+
bucket's object-storage fence lineage cannot move to the adopting binding: the bucket has more than
|
|
3438
|
+
one lineage, or its lineage does not validate, belongs to another authority or has an unfinished
|
|
3439
|
+
mutation).
|
|
3440
|
+
Only a bucket has a fence lineage, so a database never names `fence-lineage-conflict`. An
|
|
3441
|
+
adoptable bucket must have a canonical S3 name, because a binding request carries only such a
|
|
3442
|
+
name. A consumed adoption removes the legacy entry, so it never appears.
|
|
3443
|
+
2. **Relay.** `getClusterCorestoreLegacyResources { nodeId }` asks the relay for one node's
|
|
3444
|
+
inventory, answered as `TClusterCorestoreLegacyResourceInventory`: `reachable: true` with the
|
|
3445
|
+
services, or `reachable: false` with `errorCode` `CORESTORE_ENDPOINT_UNKNOWN` or
|
|
3446
|
+
`CORESTORE_UNREACHABLE` and no list. `getCorestoreLegacyResources { identity, clusterId, nodeId }`
|
|
3447
|
+
is the administrator's read through Cloudly, with `inventorySha256`
|
|
3448
|
+
(`computeClusterCorestoreLegacyResourceInventorySha256`, over the node id and the services, not
|
|
3449
|
+
the read time; `null` for an unreachable node).
|
|
3450
|
+
3. **Adoption.** `adoptCorestoreLegacyResources { identity, clusterId, nodeId,
|
|
3451
|
+
expectedInventorySha256, resources }` is the only path that creates a binding carrying a legacy
|
|
3452
|
+
bucket name. `resources` is a sorted, unique `{ serviceId, capability }` selection
|
|
3453
|
+
(`validateCorestoreLegacyResourceSelections`). Cloudly reads the inventory again, requires the
|
|
3454
|
+
expected digest, and creates each adopting binding in one transaction: enabled, placed on `nodeId`,
|
|
3455
|
+
with `corestoreLegacyAdoption { nodeId, resourceName, inventorySha256 }`, and for a bucket
|
|
3456
|
+
`objectstorageBucketName` set to the legacy bucket and `objectstorageRetention.intent` set to the
|
|
3457
|
+
legacy intent exactly, or absent when the legacy bucket has none.
|
|
3458
|
+
`validatePlatformBindingCorestoreLegacyAdoption(binding, inventory, sha)` is that rule. A resource
|
|
3459
|
+
whose adopting binding already exists is answered unchanged. `upsertPlatformBinding` keeps refusing
|
|
3460
|
+
`objectstorageBucketName`, and refuses `corestoreLegacyAdoption` and `statusReason` as well. The
|
|
3461
|
+
answer lists the bindings and the `plan`. Refusals travel as
|
|
3462
|
+
`ICorestoreLegacyAdoptionErrorData { code, retryable }`: `legacy-inventory-unreachable` (the only
|
|
3463
|
+
retryable one), `legacy-inventory-changed`, `legacy-resource-absent`, `legacy-resource-blocked`,
|
|
3464
|
+
`legacy-resource-authorized-elsewhere`, `service-absent` and `binding-exists`.
|
|
3465
|
+
4. **Plan.** `ICorestoreLegacyResourceAdoptionPlanEntry` is exactly the
|
|
3466
|
+
`{ serviceId, capability, bindingId }` object Corestore's `legacy-resource-adoption` migration
|
|
3467
|
+
reads. `validateCorestoreLegacyResourceAdoptionPlan` applies that migration's rules: a non-empty
|
|
3468
|
+
array of at most 4096 exact entries, canonical identifiers, no service capability or binding id
|
|
3469
|
+
twice, any order. `createCorestoreLegacyResourceAdoptionPlan(bindings)` builds it from the adopting
|
|
3470
|
+
bindings, sorted by service then capability. The plan restates no legacy name or retention intent:
|
|
3471
|
+
Corestore holds those itself, and the binding request that later reaches it carries the bucket and
|
|
3472
|
+
intent it compares.
|
|
3473
|
+
5. **Status.** Until the operator has run the migration, Corestore refuses the binding with a 409
|
|
3474
|
+
whose body is `{ ok: false, error, code }`. `readCorestoreLegacyAdoptionRefusal(statusCode, body)`
|
|
3475
|
+
reads `code` as a `TPlatformBindingStatusReason`, and Coreflow reports it through
|
|
3476
|
+
`updatePlatformBindingStatus { statusReason }`; `validatePlatformBindingStatusReason` pairs each
|
|
3477
|
+
reason with its one status (`getPlatformBindingStatusOfReason`):
|
|
3478
|
+
|
|
3479
|
+
| `statusReason` | Status | Corestore refusal |
|
|
3480
|
+
| --- | --- | --- |
|
|
3481
|
+
| `legacy-adoption-pending` | `provisioning` | the service owns a legacy resource of this capability that no adoption authorizes |
|
|
3482
|
+
| `legacy-adoption-conflict` | `failed` | the adoption authorizes another binding id, or it was already consumed |
|
|
3483
|
+
| `legacy-adoption-mismatch` | `failed` | the legacy identity changed since authorization, its database tenant is absent, or the bucket or retention intent differs |
|
|
3484
|
+
|
|
3485
|
+
`IPlatformBinding.statusReason` holds the reported reason; a status report without one clears it.
|
|
3486
|
+
While a binding of a service reports `legacy-adoption-pending`, the service's runtime status waits as
|
|
3487
|
+
`legacy-adoption-pending` instead of `bindings-pending`.
|
|
3488
|
+
|
|
3319
3489
|
### Launcher Environment Delivery
|
|
3320
3490
|
|
|
3321
3491
|
Launcher environment delivery uses stable `szsv-<base32-sha256>` Docker
|