# Autogen Config

> Authoring and reviewing `tools/codegen/config.yml` entries for autogenerated (serviceapi) resources. Use when creating the config.yml entry for a new autogen resource, adding or changing schema overrides (computability, sensitive, collection type, descriptions), configuring aliases, ignores, wait blocks, or version_header, or reviewing a generated schema for correctness after (re)generation.

- Skill: `mongodb/autogen-config` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mongodb/autogen-config`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mongodb/autogen-config/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: mongodb (https://skillmd.com/u/mongodb)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mongodb/autogen-config

---


# Autogen config.yml authoring and schema review

`tools/codegen/config.yml` tells the codegen pipeline which API endpoints map to each CRUD operation and how to shape the resulting Terraform schema. This skill holds all the judgment for writing an entry and for reviewing what the generator produced. Reference existing entries in config.yml for patterns matching your resource's shape.

## Writing an entry

Search `tools/codegen/atlasapispec/multi-version-api-spec.flattened.yml` for the resource's path segment and map:

- GET (single item) → `read`, POST → `create`, PATCH or PUT → `update`, DELETE → `delete`, GET (list) → `datasources.list`.
- `version_header`: the `application/vnd.atlas.<date>+json` content type on those paths. Omitting it lets the pipeline derive the version from the read operation, so set it only when the resource must be pinned to a specific version.
- Naming: the config key must **not** use the `_api` suffix, which is reserved for internal-only resources that are never registered in the provider. A user-facing `mongodbatlas_<name>` resource uses the plain name (e.g. `metric_integration`).

For the typical shape of a project-scoped entry — CRUD operations plus a `datasources` block with its own `read`/`list` and schema options — read a real entry such as `log_integration` or `metric_integration` in config.yml rather than working from a template.

### aliases

- Any resource under `/groups/{groupId}/` **must** alias `groupId: projectId`, in both `schema.aliases` and `datasources.schema.aliases`, producing the standard `project_id` attribute.
- The resource's ID attribute name should match the API path parameter. If the path param and the response body disagree (path `{myResourceId}`, body `id`), that is an API bug — report it to the owning API team, and alias to the more descriptive name (`id: myResourceId`) as a stopgap.
- Aliases match on the full camelCase API path, so the plural surface may need its own nested entries (e.g. `results.id: integrationId` — see `log_integration`). When the list results embed the scope field, keep it and alias it (`results.groupId: projectId` — see `ai_model_api_key`) rather than ignoring it.

### ignores

The generator already drops top-level `links` and pagination fields (`total_count`, `envelope`, `items_per_page`, `page_num`, `pretty`, `include_count`) everywhere — see `commonIgnoredAttributes` in `tools/codegen/codespec/config.go`. Do not re-list them. Ignore matching is exact-path, so the nested `results.links` on list data sources still needs an explicit entry, plus any other field that doesn't belong in the Terraform schema.

Secrets returned only in the create response (never populated on read or list) should be ignored on data sources, where the attribute would always be null (`ignores: ["secret", "results.secret"]` with a rationale comment — see `service_account_secret` or `ai_model_api_key`). On the resource itself the field stays, marked sensitive.

### wait

Add `wait` blocks only when the API is async (the operation returns before completing). Look for state properties like `stateName` or `status` in the response schema. Follow the anchor/merge pattern in `search_deployment_api` in config.yml: define the wait once on `create`, reuse it on `update` (`*anchor`), and merge with overrides on `delete` (`<<: *anchor`), where `DELETED` is the special target state representing a 404/empty response.

## Overrides

The `Override` struct in `tools/codegen/config/config_model.go` is the source of truth for the available set; config.yml has real examples of each. Overrides go under `schema.overrides` (resource) and `datasources.schema.overrides` (data sources), and an override can hit the same attribute on more than one surface.

Evaluate these two first — they are the easiest to miss and the most impactful when wrong:

- **`computability` → optional + computed**: if the API returns a default when the attribute is omitted, mark it optional + computed so an absent config value does not produce a perpetual non-empty plan (see `use_legacy_path_structure` under `log_integration`). The "omitting the value" acceptance test in `acceptance-test-patterns` verifies exactly this.

  ```yaml
  overrides:
    <attr>:
      # Optional but Atlas returns the default value when the attribute is omitted.
      computability:
        optional: true
        computed: true
  ```

- **`sensitive`**: if the field carries a secret (token, password, key, credential, connection string), mark it sensitive.

Then consider:

- **Collection `type`**: decide list vs set from the array's semantics, per [IPA-124 List vs Set](https://mongodb.github.io/ipa/124#list-vs-set). A list means order is meaningful and elements may repeat: the server returns a stable order and preserves the order the client provided (e.g. `environments`). A set means order is not meaningful and elements are unique: the server may return elements in any order and never returns duplicates (e.g. `roles`) — that needs `type: set`, since codegen defaults arrays to List absent an `x-xgen-array-semantic: set` declaration. Also align the same field across surfaces: the resource, singular data source, and plural data source are generated from *different endpoints*, so a field can come out as List on one and Set on another (see `roles: type: set` under `service_account_project_assignment`).
- **`immutable_computed`** (generates `UseStateForUnknown`; resource schemas only): apply to server-generated fields that are stable after creation — IDs, `created_at`/`created_by`, masked secret variants — to reduce plan verbosity. On a one-time-returned secret it also preserves the stored value across updates (see `ai_model_api_key`, where `secret` carries it for exactly that reason).
- **`description`**: each surface inherits wording from its own endpoint schema. Use the shared YAML anchors for standard fields (`*project_id_description`); otherwise prefer reporting wording inconsistencies upstream over local overrides.

Remaining override fields, one line each — read the struct comments in `config_model.go` before using them: `request_body_usage` (when a field must be sent or omitted differently on update), `skip_state_list_merge`, `plan_modifiers`, `validators`, `ignore_validators`. `SchemaOptions.discriminator_types` is a documented stopgap for oneOf/anyOf variants.

### Overrides are stopgaps — pair each with an upstream flag

The codegen consumes spec annotations natively (`tools/codegen/codespec/api_spec_schema.go`), so the durable fix is the annotation, not the override. Whenever an override compensates for missing spec information, report to the owning API team that the spec should carry the annotation, and surface the report in the PR description. Once the spec is fixed, the override should be dropped on the next regeneration.

| Local override | Spec annotation to request | Reference |
|---|---|---|
| `type: set` | `x-xgen-array-semantic: set` | [IPA-131](https://mongodb.github.io/ipa/131) |
| `computability` optional+computed | `x-xgen-server-computed-when-client-omitted: true` (escape hatch for legacy APIs; not allowed on booleans) | [IPA-131](https://mongodb.github.io/ipa/131) |
| `immutable_computed` | `x-xgen-server-computed-immutable: true` | [IPA-131](https://mongodb.github.io/ipa/131) |
| `sensitive: true` | `format: password` | [IPA-117](https://mongodb.github.io/ipa/117#sensitive-field-markings) |
| ID alias for path/body mismatch | Consistent property naming (API bug) | — |

## Post-generation schema review

The pipeline translates the spec faithfully, but the spec may not reflect how the API behaves or what Terraform users expect. After generating, read `tools/codegen/models/<name>.yaml`, `internal/serviceapi/<package>/resource_schema.go`, and the relevant spec paths, and check for:

- **Should-be-updatable fields marked create-only** (`create_only: true`, which codegen derives from `req_body_usage: omit_in_update_body` or `omit_always`): often the PATCH body is narrower than POST in the spec even though the API accepts the field on update.
- **Server-generated fields not computed**: `id`, `created_at`, `state`, `status` marked required/optional are likely wrong — response-required does not mean user-provided.
- **User-configurable fields wrongly computed**: the inverse — compare the field's presence in the POST/PATCH request bodies.
- **Missing `sensitive` markers** on secret-looking fields.
- **Discriminator scoping**: a field required for one oneOf/anyOf variant must not be required for all variants.

Report findings with severity tags (`[ERROR]` wrong computed/required classification, `[WARNING]` likely-updatable or likely-sensitive, `[INFO]` cosmetic), fix what an override can fix, and flag the rest upstream as above.

