ledgerflow-backend/template.yaml
Adam Moussa 102999165f Add DynamoDB Streams real-time PO sync and hardcode Google Client ID
- New po-sync Lambda triggered by DynamoDB Streams on the external
  purchase-orders table for near-real-time upsert into ledgerflow-pos
- GET /pos skips blocking sync when streams are configured
- Hardcode GOOGLE_CLIENT_ID fallback in CDK stack so /auth/config
  and JWT verification work without env var

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 14:29:32 -04:00

291 lines
7.7 KiB
YAML

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: LedgerFlow B2B Accounting — local SAM development
Globals:
Function:
Runtime: nodejs20.x
Architectures: [arm64]
MemorySize: 512
Timeout: 30
Environment:
Variables:
NODE_ENV: dev
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1"
POS_TABLE: ledgerflow-pos
INVOICES_TABLE: ledgerflow-invoices
EDI_TX_TABLE: ledgerflow-edi-transactions
SESSIONS_TABLE: ledgerflow-sessions
SETTINGS_TABLE: ledgerflow-settings
PURCHASE_ORDERS_TABLE: purchase-orders
EDI_INPUT_BUCKET: !Sub "ledgerflow-edi-input-${AWS::AccountId}"
EDI_OUTPUT_BUCKET: !Sub "ledgerflow-edi-output-${AWS::AccountId}"
GOOGLE_CLIENT_ID: ""
ALLOWED_ORIGIN: "*"
ALLOWED_DOMAINS: ""
EDI_PARTNERSHIP_ID: ""
EDI_TRANSFORMER_ID: ""
EDI_SENDER_ID: ""
EDI_RECEIVER_ID: ""
Resources:
# ── API Gateway ──────────────────────────────────────────────────────────────
LedgerFlowAPI:
Type: AWS::Serverless::HttpApi
Properties:
StageName: $default
CorsConfiguration:
AllowOrigins:
- "*"
- "http://localhost:3000"
AllowMethods:
- GET
- POST
- PUT
- PATCH
- DELETE
- OPTIONS
AllowHeaders:
- Content-Type
- Authorization
MaxAge: 86400
Auth:
DefaultAuthorizer: GoogleJWT
Authorizers:
GoogleJWT:
AuthorizationScopes: []
FunctionArn: !GetAtt AuthorizerFn.Arn
FunctionInvokeRole: !GetAtt AuthorizerInvokeRole.Arn
Identity:
Headers:
- Authorization
AuthorizerPayloadFormatVersion: "2.0"
EnableSimpleResponses: true
# IAM role allowing API Gateway to invoke the authorizer Lambda
AuthorizerInvokeRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: InvokeAuthorizerFn
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: lambda:InvokeFunction
Resource: !GetAtt AuthorizerFn.Arn
# ── Lambda Functions ─────────────────────────────────────────────────────────
AuthorizerFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-authorizer
Handler: index.handler
CodeUri: lambdas/authorizer/
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
AuthFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-auth
Handler: index.handler
CodeUri: lambdas/auth/
Events:
AuthConfig:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /auth/config
Method: ANY
Auth:
Authorizer: NONE
AuthConfigProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /auth/config/{proxy+}
Method: ANY
Auth:
Authorizer: NONE
AuthMe:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /auth/me
Method: ANY
Auth:
Authorizer: NONE
AuthMeProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /auth/me/{proxy+}
Method: ANY
Auth:
Authorizer: NONE
AuthLogout:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /auth/logout
Method: ANY
Auth:
Authorizer: NONE
AuthLogoutProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /auth/logout/{proxy+}
Method: ANY
Auth:
Authorizer: NONE
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
POsFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-pos
Handler: index.handler
CodeUri: lambdas/pos/
Events:
POs:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /pos
Method: ANY
POsProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /pos/{proxy+}
Method: ANY
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
InvoicesFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-invoices
Handler: index.handler
CodeUri: lambdas/invoices/
Events:
Invoices:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /invoices
Method: ANY
InvoicesProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /invoices/{proxy+}
Method: ANY
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
EDIFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-edi
Handler: index.handler
CodeUri: lambdas/edi/
Timeout: 60
Events:
EDI:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /edi
Method: ANY
EDIProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /edi/{proxy+}
Method: ANY
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
POSyncFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-po-sync
Handler: index.handler
CodeUri: lambdas/po-sync/
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
SettingsFn:
Type: AWS::Serverless::Function
Properties:
FunctionName: ledgerflow-settings
Handler: index.handler
CodeUri: lambdas/settings/
Events:
Settings:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /settings
Method: ANY
SettingsProxy:
Type: HttpApi
Properties:
ApiId: !Ref LedgerFlowAPI
Path: /settings/{proxy+}
Method: ANY
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: false
Sourcemap: true
EntryPoints: [index.js]
External: []
Outputs:
ApiUrl:
Description: Local API Gateway endpoint
Value: !Sub "https://${LedgerFlowAPI}.execute-api.${AWS::Region}.amazonaws.com"