What gets generated
sap-cap/
├── mta.yaml # MTA descriptor (srv + db-deployer + approuter modules)
├── xs-security.json # XSUAA: scopes per entity, Viewer/Editor role templates,
│ # role-collections for BTP Cockpit assignment
├── .cdsrc.json # CDS build/serve config
├── package.json # @sap/cds + @sap/xssec + mbt tooling
├── approuter/
│ └── xs-app.json # Route /api/* → srv; serve static from app/
├── db/
│ └── schema.cds # CDS entity definitions with SAP type mapping
├── srv/
│ ├── {entity}-service.cds # OData service definition per entity
│ ├── {entity}-service-handler.js # CRUD + hook handlers per entity
│ └── audit-handler.js # Emitted when audit_trail capability is selected
├── app/
│ └── {entity}/annotations.cds # Fiori UI annotations per entity
└── test/
└── {entity}.test.js # Integration tests per entity
CDS schema with correct SAP types
// db/schema.cds
namespace archiet.myapp;
entity Product {
key ID : UUID;
name : String(255);
price : Decimal;
status : String(50);
createdAt : DateTime;
updatedAt : DateTime;
}
Every CDS type is correctly mapped: String(255) for varchar, LargeString for text, Decimal for currency amounts, UUID for primary keys, DateTime for timestamps. No SQLite-to-Postgres mapping confusion.
XSUAA scopes per entity
{
"xsappname": "myapp-xsuaa",
"tenant-mode": "dedicated",
"scopes": [
{ "name": "$XSAPPNAME.myapp.product.read", "description": "Read Product" },
{ "name": "$XSAPPNAME.myapp.product.write", "description": "Write Product" }
],
"role-collections": [
{ "name": "MyApp_Viewer", "role-template-references": ["$XSAPPNAME.Viewer"] },
{ "name": "MyApp_Editor", "role-template-references": ["$XSAPPNAME.Editor"] }
]
}
MTA approuter module with forwardAuthToken
- name: myapp-approuter
type: approuter.nodejs
path: approuter
requires:
- name: myapp-xsuaa
- name: myapp-destination
- name: srv-api
group: destinations
properties:
name: myapp-srv-api
url: ~{srv-url}
forwardAuthToken: true
This is the piece that's most often wrong in hand-rolled CAP projects. The forwardAuthToken: true is required for the service to receive the XSUAA JWT. Without it, every call to the CAP service returns 401.
What ships in docs/
docs/decisions/ADR-sap-cap-btp-deployment.md— why CAP over ABAP RAP for new custom development on BTP, with rejected alternativesdocs/compliance/btp-security-posture.md— XSUAA scope model, role collection assignment procedure, zero-standing-access principledocs/runbooks/btp-mta-deploy.md— step-by-step: CF login, target org/space,mbt build,cf deploy
BusinessCapability gap analysis
When you import your existing SAP system metadata (tables, transactions, roles), Archiet automatically maps which SAP modules are present (MM, SD, FI, CO, HR, etc.) to a standard Business Capability Model. The gap analysis compares your detected capabilities against the 60-capability BCM for your modules and surfaces what's missing.
A typical output:
Finance domain — 6/6 capabilities covered (100%)
✓ Financial Accounting | ✓ Accounts Payable | ✓ Accounts Receivable
✓ General Ledger | ✓ Financial Reporting | ✓ Fixed Asset Management
Procurement domain — 3/5 capabilities covered (60%)
✓ Procurement Management | ✓ Inventory Management | ✗ Supplier Collaboration
✗ Contract Lifecycle Management | ✓ Purchase Order Management
Internal links
- SAP BTP Genome for the full platform topology generator
- SAP RISE migration use case for RISE readiness assessment
- Internal tools use case for non-SAP internal tooling
CTA
Try it — free plan, no credit card. archiet.com.
Generate a SAP CAP project. Open mta.yaml and xs-security.json. See whether the XSUAA scopes are the shape you'd ship.