This file provides guidance to AI agents when working with code in this repository.
IAM Floyd is an AWS IAM policy statement generator with a fluent interface. It generates TypeScript classes for all AWS services and their actions, resources, and condition keys from AWS documentation. The project supports both standalone usage (iam-floyd) and AWS CDK integration (cdk-iam-floyd).
lib/generated/policy-statements/- Generated TypeScript class per AWS service (460+ files)lib/generated/index.ts- Re-exports all service classeslib/generated/aws-managed-policies/- Generated AWS managed policieslib/shared/- Hand-written core:PolicyStatement,All,Operator,AccessLevellib/collection/- Predefined policy collection utilitieslib/generator/- Scrapes AWS docs and generateslib/generated/viacheerio+ts-morph
Built in 10 numbered layers (lib/shared/policy-statement/):
1-base → 2-conditions → 3-actions → 4-resources → 5-effect
→ 6-arn-defaults → 8-principals → 10-final (PolicyStatement)
Each *.CDK.ts file is the CDK variant of that layer (swapped in by bin/mkcdk.ts).
One codebase produces two npm packages:
iam-floyd- Standalone (uses built-in base class)cdk-iam-floyd- Extendsaws_iam.PolicyStatementfrom AWS CDK
bin/mkcdk.ts transforms between variants by swapping *.CDK.ts files and rewriting constructors.
make build # tsc --build --force tsconfig.main.json
make package # build + npm pack
make clean # remove node_modules, *.js, *.d.ts
make install # clean + npm imake generate # generate lib/generated/ from AWS docs (25hr cache)
make generate-force # NOCACHE=1 - ignores time-based cache
make index-managed-policies # regenerate AWS managed policies indexThe project has no unit test framework. Tests are integration-style: TypeScript examples are compiled, run, and their output is diffed against stored .result files.
make test # compile examples/ + diff against *.result files (standalone)
make test-typescript # same, via Test.TypeScript.Makefile
make cdk-test # CDK test: real deploy + destroy via AWS CDK
make cdk-all # cdk + install + build + cdk-testRun a single example test manually:
# 1. Compile a single example
npx tsc -p tsconfig.test-iam-floyd.json
# 2. Run and compare output
node examples/allow/allow.js > /tmp/out.txt
diff /tmp/out.txt examples/allow/allow.result
# Or run the integration test harness directly:
npx ts-node test/main.tsRegenerate expected results (after intentional changes):
make regenerate-code-example-resultsmake eslint # npx eslint .make cdk # transforms codebase to CDK variant (modifies lib/shared, lib/generated, package.json)
make uncdk # reverts via git stash (lib/generated, lib/shared, package.json)The generator scrapes live AWS docs, which sometimes contain errors or inconsistencies. fixes.ts is the central place to patch these before code is generated. When the generator produces wrong output, add a fix here rather than editing generated files.
Each top-level key is the URL slug of a service's IAM docs page (e.g. ec2, ssm, 'neptune-db'). Supported sub-keys:
| Sub-key | Effect |
|---|---|
ignore: true |
Skip generating this service entirely (used for EOL services) |
name: 'slug' |
Override the generated filename and class name (needed when the same service prefix spans multiple doc pages, e.g. pinpointemailservice → ses-pinpoint) |
service: 'prefix' |
Override the IAM service prefix used in the generated code |
resourceTypes.<name>.arn |
Replace the ARN template for a resource type with a corrected one |
conditions.<key>.key |
Rewrite the condition key string (used when docs have a concrete example key like RequestTag/tag-key instead of the parametric form RequestTag/${TagKey}) |
conditions.<key>.methodName |
Override the generated ifXxx() method name for a condition |
conditions.<key>.operator.type |
Override the inferred operator type (e.g. force date instead of string) |
conditions.<key>.operator.override |
Set typeOverride on the condition (used for custom operator generation) |
conditionFixer(service, condition)— Normalises condition types (ArrayOfString→string,long→numeric, etc.) and applies any key/operator overrides fromfixes. Logs yellow[L1/L2 fix …]messages to stdout.conditionKeyFixer(service, key)— Rewrites a raw condition key string using anyconditions.<key>.keyoverride defined infixes.arnFixer(service, resource, arn)— Applies a cascade of ARN normalisation rules:- Uppercases the first letter of every
${placeholder}(L1) - Replaces trailing
*wildcards with${ResourceName}(L2) - Deduplicates repeated placeholder names by appending a counter (L2, Rekognition workaround)
- Applies the hard-coded ARN override from
fixesif present (L3) After fixing, validates the result against the canonical ARN regex and warns if it doesn't match (with a known-good exception list).
- Uppercases the first letter of every
serviceFixer(service)— Rewrites the IAM service prefix if aserviceoverride is defined infixes.
- Find the service's URL slug from its IAM docs URL (e.g.
https://…/list_amazons3.html→ slug iss3). - Add an entry to the
fixesobject inlib/generator/fixes.ts. - Run
make generate-forceto regenerate with the fix applied.
CRITICAL: Never manually edit files in lib/generated/.
They are auto-generated from AWS documentation and will be overwritten on next make generate.
Allowed manual edits:
lib/shared/- Core shared classeslib/collection/- Predefined collectionslib/generator/- Generation logic and fixesbin/- CLI scriptstest/- Integration test scriptsexamples/- Example files and their.resultcounterparts
- Indentation: 2 spaces (tabs only in Makefiles)
- Quotes: Single quotes in TypeScript/JS; double quotes in YAML/JSON
- Trailing newline: Required on all files
- No trailing whitespace
- Line endings: LF (
\n)
Run make eslint to check; Prettier is enforced via eslint-plugin-prettier.
Strict settings enforced in tsconfig.json:
strict: true
noImplicitAny: true
strictNullChecks: true
strictPropertyInitialization: true
noUnusedLocals: true
noUnusedParameters: true
noImplicitReturns: true
target: ES2020, module: CommonJS
- No
any: Prefer explicit types or generics. - Unused vars: Prefix with
_to suppress (argsIgnorePattern: ^_). - Naming conventions: Enforced via
@typescript-eslint/naming-convention. UsecamelCasefor variables/functions,PascalCasefor classes/interfaces. - Template literals: Prefer
`${x}`over'a' + x(prefer-template: error). - Deprecated APIs:
deprecation/deprecationrule is set toerror— do not use deprecated APIs. - No
require(): Use ESimport/export.
- Use named imports where possible:
import { Foo } from './foo' - Relative imports within
lib/; absolute fornode_modules lib/generated/is excluded from ESLint entirely
All service classes return this to allow chaining:
new Statement.S3()
.allow()
.toGetObject()
.on('arn:aws:s3:::my-bucket/*')
.ifAwsSourceVpc('vpc-123');- All public methods in generated files have JSDoc with Access Level, conditions, resources, and an AWS docs URL
- In
lib/shared/, document non-obvious public methods and parameters
export class ServiceName extends PolicyStatement- Action methods:
toXxx()— e.g.,toGetObject(),toListBuckets() - Resource methods:
onXxx()— e.g.,onBucket(),onObject() - Condition methods:
ifXxx()— e.g.,ifAwsSourceIp(),ifS3Prefix() - All methods return
thisfor chaining
tsconfig.json- Dev/generation (includes all files, uses SWC viats-node)tsconfig.main.json- Production build (excludesbin/,lib/generator/,test/, CDK files)tsconfig.test-iam-floyd.json- Compilesexamples/excluding.cdk.tstsconfig.test-cdk-iam-floyd.json- Compilesexamples/**/*.cdk.ts
SWC is used for faster transpilation: "ts-node": { "swc": true } in tsconfig.json.
Follow conventional commits:
feat: description- New featuresfix: description- Bug fixeschore(deps): description- Dependency updatesdocs: description- Documentation changesrefactor: description- Code refactoring- Simple prose for automated updates:
"Updates AWS managed policies"
Never commit directly to main. Use a feature branch. Commits may fail spell-checking; add missing words with dict-add <word>.
generate.yml- Daily: scrapes AWS docs, bumps patch version, opens PR withautomergelabelindex-managed-policies.yml- Daily: updates managed policies, opens PR withautomergelabeltest-and-publish.yml- On PR/push to main:make install test-typescript+ CDK deploy test + npm publishautomerge.yml- Auto-merges PRs labeledautomergeafter tests passtest-docs.yml- Builds Sphinx docs ondocs/**changes