Adds three handbook pages covering conventions that were previously scattered across feedback memories or rederived from scratch each time: - bedrock.md captures the cross-region inference profile requirement for Claude 4.x Bedrock Agents and the alias-version pinning gotcha, plus the IAM resource pattern and the KB Docker requirement. - dev-environment.md documents the workstation directory layout, pyenv/Node conventions, the macOS launchd/TCC sandbox gotcha, and cleanup cadence. - lambda-template.md provides a minimal SAM scaffold that follows the Lambda defaults already in aws-infrastructure.md (Python 3.12, arm64, explicit 60-day log retention, scoped Secrets Manager access, module-level secret cache). Also extends two existing pages: - sam-project-layout.md gains a Lambda Layers section with the BuildMethod nesting pattern that caused a ~22-hour production outage when violated. - naming-conventions.md adds a Legacy Stacks note acknowledging that pre-convention PascalCase stacks (SeaHavenDoorUnlockStack, WorkorderIngestStack) stay as-is rather than risk stack replacement.
3.1 KiB
SAM Project Layout
Standard Directory Structure
project-name/
├── template.yaml # SAM template at root
├── samconfig.toml # Deploy config (gitignored)
├── samconfig.toml.example # Template for onboarding (committed)
├── src/
│ ├── function_name/
│ │ ├── app.py # Lambda handler
│ │ └── requirements.txt # Per-function dependencies
│ └── shared/ # Shared layer code (if needed)
└── .gitignore
File Purposes
template.yaml
The SAM/CloudFormation template. Lives at the project root. Defines all Lambda functions, IAM roles, API Gateway endpoints, DynamoDB tables, and other resources.
samconfig.toml
Contains real ARNs, S3 bucket names, and deploy parameters. Gitignored because it varies per environment and may contain account-specific values.
samconfig.toml.example
A committed template showing the expected structure and parameter names. New contributors copy this to samconfig.toml and fill in their values.
src/function_name/
One directory per Lambda function. Each contains its own handler (app.py) and dependencies (requirements.txt). This keeps functions independently deployable and avoids bloating one function with another's dependencies.
src/shared/
Optional. Used for code shared across multiple functions, typically deployed as a Lambda layer. See the next section for layout details.
Lambda Layers
When sharing code across functions via a layer, the source layout matters because SAM transforms ContentUri depending on whether BuildMethod is set.
Correct layout (with BuildMethod)
src/shared/
├── shared/ # Package goes here directly — SAM wraps in python/ at build time
│ ├── __init__.py
│ └── utils.py
└── requirements.txt # Layer-level pip dependencies
Template:
SharedLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: my-stack-shared
ContentUri: src/shared/
CompatibleRuntimes:
- python3.12
CompatibleArchitectures:
- arm64
Metadata:
BuildMethod: python3.12
BuildArchitecture: arm64
BuildMethod nesting gotcha
With BuildMethod: python3.12, SAM copies ContentUri into a python/ subdirectory during build, then pip-installs requirements.txt deps into that same python/ directory.
Do not include a python/ wrapper in your source — SAM adds it. The wrong layout:
src/shared/
├── python/ # SAM wraps this again → python/python/shared/ — module unreachable
│ └── shared/
└── requirements.txt
A real production incident (~22 hours of outage) traced to this exact pattern when a refactor moved layer code under an extra python/ directory.
Without BuildMethod (raw zip)
If the layer has no pip dependencies and you omit BuildMethod, SAM zips ContentUri as-is — you DO need the python/ wrapper. Reserve raw zip for layers that ship only Python source.
Standard .gitignore
.aws-sam/
__pycache__/
*.pyc
.env
samconfig.toml