Skip to content

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-auth client 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:

  • prefix must 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 all for custom providers (PLATFORM, TECH_DEBT, FORBIDDEN); -filter cloud drops 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).

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)

  1. Inventory real import paths from a pilot service (grep go.mod / pom.xml / requirements.txt, not guesses).
  2. Author lens from platform-adoption or tech-debt template.
  3. Smoke-scan pilot repo; tune prefixes and Grok rules with -log-level debug.
  4. Pin version in CI (/v1.2.0/ not only latest).
  5. Add catalog + pack when multiple teams need the same recipe ids.
  6. 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