Enterprise lenses and catalogs
How platform and security teams document internal developer platform (IDP) libraries, shared SDKs, and org-specific APIs with CCE—without waiting on upstream releases.
What
| Term | What it is |
|---|---|
| Lens | A YAML mapper (*_lenses.yaml) that turns static call sites into structured rows: provider, resource, operation (plus optional OpenRewrite hints). Passed via -mapper-file or a recipe lens_url. |
| Recipe | A catalog entry: metadata (id, title, languages, filter) pointing at a lens. Discovered via cce catalog and run via cce run -recipes or -pack. |
| Catalog | catalog.json — list of recipes (pkg/recipes/catalog.json is embedded in the cce binary; enterprises can host their own). |
| Pack | packs.json — named bundle of recipe ids (e.g. cloud entitlements + your IDP inventory in one parse). |
CCE is read-only inventory: lenses find call sites; they do not rewrite code. Apply steps stay in OpenRewrite, internal codemods, or manual migration.
Why
Enterprises need repeatable answers to questions like:
- Which services still call raw
boto3/ AWS SDK instead of our platform SDK? - Where is the deprecated
com.corp.legacy-authclient still used? - Can CI fail when a forbidden internal package appears in a PR?
A lens encodes what to detect (package prefixes, wrapper shapes). A catalog encodes how teams discover and run those checks (cce catalog, cce run -pack, remote URLs in CI). Hosting both internally keeps golden-path and compliance rules under your change control, independent of releases.stackgen.com.
How easy is it?
| Goal | Difficulty | Typical work |
|---|---|---|
| Scan internal libs with a custom lens | Low | Copy a template, set import prefixes, smoke-scan one repo |
| Wrapper clients (non-standard method names) | Medium | Grok rules per client shape — see prowler example |
| Private catalog + packs for hundreds of repos | Low–medium | JSON entries + HTTPS hosting; no Go changes |
| Contribute lenses to public StackGen releases | Medium | Upstream PR, fixtures, publish CI |
Most IDP teams start with Path A (lens only), then add a catalog when they want cce run -pack and shared recipe ids.
Path A — Custom lens only (fastest)
When: Pilot repo, iterating on YAML, or a single pipeline that pins -mapper-file.
Why: No binary rebuild, no catalog maintenance; HTTPS or repo-relative path is enough.
1. Pick a template
| Template | Use for |
|---|---|
| platform-adoption | Internal platform SDK vs direct cloud SDK |
| tech-debt-inventory | Deprecated / forbidden libraries |
| prowler | Wrapper clients (s3_client.buckets.values() style) |
Replace example prefixes (github.com/acme/platform-sdk/, com.acme.platform.) with your org’s real import paths.
2. Author YAML
Rules live under definition.language.<go|java|python|javascript>. Critical constraints:
prefixmust match the start of the method name CCE extracts (often full FQN, not import alias).- Use inline regex
(?<name>[a-z0-9_]+)when identifiers contain underscores —%{WORD}does not match underscores. - Use
-filter allfor custom providers (PLATFORM,TECH_DEBT,FORBIDDEN);-filter clouddrops non-cloud providers.
See Custom lens YAML for syntax, dataTables, prefixes_from, and openrewrite_recipe hints.
Example (Go internal platform SDK):
definition:
language:
go:
- name: "Corp platform SDK"
prefix: "github.com/corp/platform-sdk/"
provider: PLATFORM
- name: "Direct AWS SDK v2 (bypass)"
prefix: "github.com/aws/aws-sdk-go-v2/"
provider: DIRECT_CLOUD
providers:
PLATFORM:
servicenameMapping: {}
DIRECT_CLOUD:
servicenameMapping: {}
3. Scan
cce -folder . -language AUTO -filter all \
-mapper-file ./corp/idp-platform-lenses.yaml \
-format json -output idp-inventory.json
jq '.summary' idp-inventory.json
4. Debug unmatched calls
cce -folder . -language AUTO \
-mapper-file ./corp/idp-platform-lenses.yaml \
-filter all -log-level debug -format text 2>&1 | less
Look for We do not support this method name yet (prefix mismatch) or could not map the method call (rule mismatch).
5. Host for CI (recommended)
Upload lens YAML to internal HTTPS (S3, Artifactory, GHE raw). CCE requires HTTPS for remote mappers, 10MB max, no redirects.
cce -folder . -language AUTO -filter all \
-mapper-file https://artifacts.corp.example/cce/lenses/idp/v1.2.0/idp_lenses.yaml \
-format json -output idp.json
Mapper precedence: With -mapper-file, your lens runs first; built-in cloud rules fill gaps when the lens does not match (Agents.md).
Path B — Register a catalog recipe
When: Teams should run cce catalog, cce run -recipes <id>, or a shared pack across many repos.
Why: Standardizes recipe ids, documents example_cli, and separates lens artifact (versioned YAML) from discovery (JSON catalog).
1. Place the lens
Convention: docs/use-cases/guides/<recipe-id>/<recipe-id>_lenses.yaml in your fork, or any path in a private repo.
2. Add a catalog entry
Edit your copy of the catalog (fork: pkg/recipes/catalog.json; enterprise: hosted catalog.json):
{
"id": "corp-idp-inventory",
"version": "1.0.0",
"title": "Corp internal platform SDK inventory",
"description": "Call sites for corp platform SDK vs direct cloud usage.",
"languages": ["GO", "JAVA", "PYTHON", "AUTO"],
"filter": "all",
"lens_path": "docs/use-cases/guides/corp-idp/corp-idp_lenses.yaml",
"lens_url": "https://artifacts.corp.example/cce/lenses/corp-idp/v1.0.0/corp-idp_lenses.yaml",
"proof_status": "lens-only",
"example_cli": "cce -folder . -language AUTO -mapper-file https://artifacts.corp.example/cce/lenses/corp-idp/v1.0.0/corp-idp_lenses.yaml -filter all -format json -output idp.json"
}
| Field | Guidance |
|---|---|
id |
Lowercase, hyphenated; stable once CI depends on it |
filter |
all for custom providers; cloud for cloud-mapped rows only |
lens_path |
Used when the file exists in the scanned repo checkout |
lens_url |
Used when local path is missing — prefer this in CI |
3. Optional pack
In packs.json:
{
"id": "corp-platform-pack",
"title": "Corp platform governance",
"description": "Cloud entitlements plus internal platform SDK inventory.",
"recipe_ids": ["cloud-entitlements", "corp-idp-inventory"]
}
cce run -folder . -language AUTO -pack corp-platform-pack -output platform.json
One parse pass; merged JSON report (recipes README).
4. Self-hosted catalog (enterprise)
No upstream merge required:
cce catalog --remote \
-catalog-url https://artifacts.corp.example/cce/recipes/latest/catalog.json \
-packs-url https://artifacts.corp.example/cce/recipes/latest/packs.json
cce run -folder . -language AUTO -pack corp-platform-pack -remote \
-catalog-url https://artifacts.corp.example/cce/recipes/latest/catalog.json \
-packs-url https://artifacts.corp.example/cce/recipes/latest/packs.json \
-output platform.json
5. Optional CI policy
docs/recipes/policies/*.yaml + cce diff baseline.json current.json -policy … — see recipes README.
6. Public StackGen publish (optional)
Merging to appcd-dev/cce main runs publish CI (scripts/publish-cce-lenses.sh) → https://releases.stackgen.com/cce/lenses/... and .../cce/recipes/latest/. Use this when the lens should be public; keep private IDP rules on internal HTTPS only.
Enterprise workflow (checklist)
- Inventory real import paths from a pilot service (grep
go.mod/pom.xml/requirements.txt, not guesses). - Author lens from platform-adoption or tech-debt template.
- Smoke-scan pilot repo; tune prefixes and Grok rules with
-log-level debug. - Pin version in CI (
/v1.2.0/not onlylatest). - Add catalog + pack when multiple teams need the same recipe ids.
- Document limitations: internal facades may hide underlying cloud APIs — see KNOWN_LIMITATIONS.
Common pitfalls
| Pitfall | What to do |
|---|---|
| Prefix does not match extracted FQN | Run debug scan; copy exact method from JSON output into lens prefix / rule |
filter cloud hides PLATFORM rows |
Use -filter all for IDP inventory |
| Overlapping lens rules | More specific rules first; first match wins |
| Wrapper hides S3/KMS calls | Scan the SDK repo or add wrapper-specific rules; see entitlements guide |
| Expecting one row with two operations | One call site → one operation; aggregate for IAM separately |