Backend Parity Checklist
The repository supports AWS and Azure backends without forking the application data model. Site features should be implemented once against the shared workspace model, then mapped to local storage, AWS, and Azure through provider configuration and service adapters.
The active provider selection lives in src/config/backend.js. That file is generated by npm run init:backend and should contain only non-secret deployment metadata: provider, environment, region or location, storage resource names, database resource names, identity service label, and notification service label. The coordinating node can still register additional provider connections in .wm-data/connections.json for sync.
Use this checklist after reading the shared Cloud Backend Setup page and the concrete AWS Backend Setup or Azure Backend Setup page. It is not a provisioning runbook; it is the review surface that keeps the provider-specific runbooks, scripts, and shared model aligned.
Current Repository State
At the time this doc was written, src/config/backend.js selects AWS for the dev environment:
provider: "aws"
environment: "dev"
region: "us-east-1"
This does not remove Azure support. AWS and Azure defaults, labels, and service mappings remain in src/lib/workspace-model.js under backendProviderCatalog. Tests verify that provider selection changes labels and storage_provider, while keeping project-owned paths provider-neutral.
The static frontend still has one active deployment context, but the local coordinating-node runtime can register multiple backend connections. That is the sync boundary: local, AWS, and Azure surfaces exchange provider-neutral sync items with stable IDs, versions, checksums, timestamps, deleted markers, and conflict records. This avoids embedding provider-specific dual-write logic in the browser.
Shared Application Contract
Both providers must support the same application contracts:
- Normalize signed-in provider identity into an application user.
- Return session context with accounts, teams, projects, grants, preferences, and effective capabilities.
- Store accounts, account members, teams, team members, projects, project grants, file/document artifacts, invitations, metadata records, write events, and notification preferences.
- Generate upload URLs only after project permission checks.
- Store raw and processed files under the same provider-neutral document-artifact prefix shape.
- Compute effective project permissions from application records, not from cloud admin status alone.
- Emit administrative and file/document-artifact events into the selected provider's notification/event stack.
Feature work should preserve this contract. If a UI feature adds a new field to a project, document, account, team, grant, metadata record, or write event, update the shared model and both backend docs in the same change.
Provider Mapping
| Concern | AWS | Azure |
|---|---|---|
| User sign-in and deployment claims | Cognito | Microsoft Entra External ID |
| API runtime | API Gateway + Lambda | Azure Functions or Container Apps behind API Management |
| Application records | DynamoDB | Cosmos DB for NoSQL |
| Raw and processed files | S3 | Blob Storage |
| Upload URL | S3 presigned URL | Blob delegated upload URL or SAS issued by the API |
| Administrative event bus | EventBridge | Event Grid |
| SES | Azure Communication Services Email | |
| Secrets and runtime configuration | Secrets Manager or Parameter Store | Key Vault or App Configuration |
Backend Selection File
The generated src/config/backend.js file is intentionally safe to commit when it contains only resource identifiers:
export const backendSelection = {
provider: "aws",
environment: "dev",
region: "us-east-1",
storage: {
bucket: "workspace-management-dev-documents",
privatePrefixMode: "workspace-model"
},
database: {
table: "workspace-management-dev",
itemContainer: "workspace_items"
},
identity: {
service: "Cognito"
},
notifications: {
service: "EventBridge + SES"
}
};
Azure uses the same shape, but replaces region with location and names Azure resources:
export const backendSelection = {
provider: "azure",
environment: "dev",
location: "eastus",
storage: {
account: "workspacemanagedevdocs",
container: "workspace-documents",
privatePrefixMode: "workspace-model"
},
database: {
account: "workspace-management-dev-cosmos",
database: "workspace",
container: "workspace_items",
itemContainer: "workspace_items"
},
identity: {
service: "Microsoft Entra External ID"
},
notifications: {
service: "Event Grid + Azure Communication Services Email"
}
};
Do not put cloud credentials, connection strings, account keys, SAS tokens, Cognito secrets, Entra secrets, or personal login material in this file.
Parallel Maintenance Rules
Keep these layers separate when editing site features:
- Shared model:
src/lib/workspace-model.jsdefines application object shape, helper functions, backend catalog labels, permissions, storage prefixes, and version/history record creation. - UI:
src/components/workspace-management-app.jsrenders the prototype and should call shared helpers for backend labels, storage paths, metadata records, and write events. - Provider config:
src/config/backend.jsselects the active provider for the environment. - Provider setup docs and scripts:
src/docs/aws.md,src/docs/azure.md,scripts/setup-aws-backend.sh, andscripts/setup-azure-backend.shexplain and provision equivalent baseline resources. - Deployment scripts:
scripts/deploy-aws-site.shandscripts/deploy-azure-site.shpublish static frontend assets and should remain separate from private file/artifact storage.
When adding a feature:
- Add provider-neutral fields and helper behavior to
src/lib/workspace-model.js. - Add or update tests in
tests/workspace-model.test.mjs. - Render the feature from shared helpers in the UI.
- Update AWS and Azure docs when storage, identity, database, API, or notification behavior changes.
- Keep
src/config/backend.jslimited to selected provider and resource names. - Avoid provider-specific branching in UI components unless it is presentation-only labeling.
AWS Configuration
AWS backend setup is selected with:
npm run init:backend -- --provider aws --environment dev --prefix workspace-management --region us-east-1
Baseline provisioning uses:
npm run setup:aws
The setup script creates or hardens:
- Private S3 bucket for raw and processed project artifacts.
- DynamoDB table with
PK,SK, and four GSIs for account, team, user, and project access patterns.
AWS environment variables include:
AWS_PROFILEAWS_REGIONAWS_S3_BUCKETAWS_DYNAMODB_TABLEAWS_TAGS
The private artifact bucket is separate from any public static website bucket used by frontend deployment.
Azure Configuration
Azure backend setup is selected with:
npm run init:backend -- --provider azure --environment dev --prefix workspace-management --location eastus
Baseline provisioning uses:
npm run setup:azure
The setup script creates or hardens:
- Resource group.
- Private StorageV2 account and Blob container.
- Cosmos DB SQL database and item container with
/pkas the partition key. - Storage Blob Data Contributor role assignment for the signed-in setup user when available.
Azure environment variables include:
AZURE_RESOURCE_GROUPAZURE_LOCATIONAZURE_STORAGE_ACCOUNTAZURE_STORAGE_CONTAINERAZURE_COSMOS_ACCOUNTAZURE_COSMOS_DATABASEAZURE_COSMOS_CONTAINERAZURE_COSMOS_ENABLE_FREE_TIERAZURE_TAGS
The private Blob container is separate from any Azure Storage static website $web container used by frontend deployment.
Data Storage Architecture
Both providers should persist the same logical records.
AWS DynamoDB:
- Table primary key:
PK,SK. - GSI1: account projects, members, and teams.
- GSI2: team membership and project grants.
- GSI3: user memberships, invitations, and preferences.
- GSI4: project grants and artifacts.
Azure Cosmos DB:
- One SQL API database for the baseline implementation.
- One item container named
workspace_items. - Partition key path:
/pk. - Item
pkvalues mirror the same logical partition groups used by the DynamoDB single-table model.
The backend should treat DynamoDB and Cosmos DB as persistence adapters for the same item families. The application should not need different project, file/document artifact, team, or account fields for each provider.
Versioning And Audit Records
Version and history behavior is provider-neutral:
- Project and document artifact rows hold current state.
- Metadata records are append-only snapshots keyed by document and timestamp.
- Write events are append-only user-authored records keyed by document and timestamp.
- Derived processing outputs are stored as child artifacts and can be regenerated or superseded without replacing the raw upload record.
- Grants and invitations include creator and creation timestamp and should be retained for audit history.
For concurrency in a production backend, add provider-specific conditional writes while preserving the same logical version model:
- DynamoDB: conditional update on
updated_at,version, or an entity tag field. - Cosmos DB: conditional write using
_etag.
Those concurrency fields are implementation details. They should not change the user-visible object hierarchy.
Cloud Account Versus Application Account
The word account appears in two places:
- Cloud account or subscription: the AWS account or Azure subscription/resource group that owns infrastructure.
- Application account: a client organization, consulting firm, or personal workspace inside the app.
Application account records must remain portable across AWS and Azure. Moving the deployment from AWS to Azure should change where records are stored and where files live, not what an application account means.
Parity Checklist
Before merging backend-affecting feature work, verify:
npm testpasses.npm run buildpasses.- New fields are documented in
data-identity-model.md. - AWS and Azure backend setup docs still describe equivalent persistence, identity, storage, and notification behavior.
backendProviderCataloghas correct labels and default values for both providers.- Object/blob paths still use the project-owned prefix shape.
- No secrets were added to
src/config/backend.js, docs, tests, or generated frontend output.