Summary
aio console workspace api add --service-code X against a workspace that already has another API subscribed silently replaces the subscription rather than appending to it. The previously-subscribed APIs (and their credential scopes) are removed.
This is contrary to the command name (add), the help text ("Add API service(s) to a Workspace"), and the v5.3.0 release notes which describe it as subscribing one or more API services.
Environment
@adobe/aio-cli 11.1.0 (macOS arm64, node v24.14.1)
@adobe/aio-cli-plugin-console 5.3.0 (the version that introduced this command)
Repro
Start with a workspace that has exactly one API subscribed — for example App Builder Data Services (AppBuilderDataServicesSDK), which adds the adobeio.abdata.* scopes to the OAuth Server-to-Server credential.
# Verify starting state
aio console workspace api list \
--projectName <project> --workspaceName <workspace> --json
# -> [{ "sdkCode": "AppBuilderDataServicesSDK", ... }]
# "Add" I/O Management API
aio console workspace api add \
--projectName <project> --workspaceName <workspace> \
--service-code AdobeIOManagementAPISDK
# -> Successfully added API(s) AdobeIOManagementAPISDK to Workspace <workspace>.
# Verify
aio console workspace api list \
--projectName <project> --workspaceName <workspace> --json
Expected
Workspace ends up subscribed to both AppBuilderDataServicesSDK and AdobeIOManagementAPISDK. Credential scopes accumulate (adobeio.abdata.* + I/O Management scopes).
Actual
Workspace is subscribed to only AdobeIOManagementAPISDK. AppBuilderDataServicesSDK is silently removed, along with its adobeio.abdata.read|write|manage scopes on the OAuth Server-to-Server credential. Calling api add again with AppBuilderDataServicesSDK swaps it back the other way.
This is a set/replace semantic, not add/append. It's particularly dangerous because:
- The success message says "added", with no mention that anything was removed.
- Removed scopes mean runtime tokens minted from that credential lose access to whatever APIs depended on them, breaking deployed apps without any deploy-time signal.
Workaround
Pass all desired service codes in a single --service-code argument (comma-separated). This works as expected and ends up with all listed services subscribed:
aio console workspace api add \
--projectName <project> --workspaceName <workspace> \
--service-code "AdobeIOManagementAPISDK,AppBuilderDataServicesSDK"
Suggested fixes
- Make
api add truly additive — read the current subscription list and merge with the requested codes before persisting.
- If the API truly is set-based under the hood, rename the command (
api set?) and/or add an explicit warning when removing services, or surface a --replace / --merge flag with --merge as the default.
- The success message should enumerate the post-state (
Workspace <name> is now subscribed to: A, B, C), not just echo what was passed in.
Impact
We hit this on a production-ish App Builder app while following the official CI/CD using GitHub Actions guide, which directs users to add the I/O Management API to enable CI deploys. The "add" silently removed the App Builder Data Services SDK from the workspace's S2S credential, which in turn removed the adobeio.abdata.* scopes that @adobe/aio-lib-db needs at runtime. The deployed actions would have started 401-ing on database calls on next invocation, with no signal at deploy time.
We caught it before it shipped, but only because we happened to verify the workspace state after running api add. Most users following the doc will not.
Summary
aio console workspace api add --service-code Xagainst a workspace that already has another API subscribed silently replaces the subscription rather than appending to it. The previously-subscribed APIs (and their credential scopes) are removed.This is contrary to the command name (
add), the help text ("Add API service(s) to a Workspace"), and the v5.3.0 release notes which describe it as subscribing one or more API services.Environment
@adobe/aio-cli11.1.0 (macOS arm64, node v24.14.1)@adobe/aio-cli-plugin-console5.3.0 (the version that introduced this command)Repro
Start with a workspace that has exactly one API subscribed — for example App Builder Data Services (
AppBuilderDataServicesSDK), which adds theadobeio.abdata.*scopes to the OAuth Server-to-Server credential.Expected
Workspace ends up subscribed to both
AppBuilderDataServicesSDKandAdobeIOManagementAPISDK. Credential scopes accumulate (adobeio.abdata.*+ I/O Management scopes).Actual
Workspace is subscribed to only
AdobeIOManagementAPISDK.AppBuilderDataServicesSDKis silently removed, along with itsadobeio.abdata.read|write|managescopes on the OAuth Server-to-Server credential. Callingapi addagain withAppBuilderDataServicesSDKswaps it back the other way.This is a
set/replacesemantic, notadd/append. It's particularly dangerous because:Workaround
Pass all desired service codes in a single
--service-codeargument (comma-separated). This works as expected and ends up with all listed services subscribed:Suggested fixes
api addtruly additive — read the current subscription list and merge with the requested codes before persisting.api set?) and/or add an explicit warning when removing services, or surface a--replace/--mergeflag with--mergeas the default.Workspace <name> is now subscribed to: A, B, C), not just echo what was passed in.Impact
We hit this on a production-ish App Builder app while following the official CI/CD using GitHub Actions guide, which directs users to add the I/O Management API to enable CI deploys. The "add" silently removed the App Builder Data Services SDK from the workspace's S2S credential, which in turn removed the
adobeio.abdata.*scopes that@adobe/aio-lib-dbneeds at runtime. The deployed actions would have started 401-ing on database calls on next invocation, with no signal at deploy time.We caught it before it shipped, but only because we happened to verify the workspace state after running
api add. Most users following the doc will not.