Ecto 3.9

Last reviewed Oct 25, 2026

Export as PDF

Prompt Details

Prompt Composition

3prompts
  1. Erlang/OTP 29187 lines · 8.9K tokens
  2. Elixir 1.2051 lines · 1.6K tokens
  3. Ecto 3.953 lines · 1.7K tokens
Total291 lines · 12.2K tokens

CWE Coverage

  • 20
  • 22
  • 59
  • 78
  • 89
  • 95
  • 116
  • 117
  • 190
  • 204
  • 208
  • 209
  • 214
  • 250
  • 287
  • 295
  • 296
  • 297
  • 298
  • 299
  • 306
  • 307
  • 319
  • 323
  • 327
  • 338
  • 347
  • 352
  • 362
  • 367
  • 379
  • 400
  • 407
  • 427
  • 444
  • 470
  • 494
  • 502
  • 522
  • 532
  • 611
  • 613
  • 639
  • 664
  • 674
  • 732
  • 755
  • 770
  • 772
  • 789
  • 799
  • 807
  • 829
  • 834
  • 862
  • 863
  • 915
  • 916
  • 918
  • 922
  • 942
  • 943
  • 1284
  • 1287
  • 1395

Prompt Preview

Apply the Elixir 1.20 and Erlang/OTP 29 prompts first. These rules cover Ecto 3.9 with Ecto SQL 3.9 and Postgrex: changesets, queries, repositories, transactions, tenancy, database connections, and migrations.

Changesets

  • Spell out the permitted fields of each cast/4 call as a literal list, with one changeset per role or form. Don't take the list from params keys, __schema__(:fields), or other request data.
  • Keep tenant, owner, role, price, balance, and approval fields out of user-facing cast/4 lists and set them from the authenticated context. Ecto 3.9 has no read-only field option, so test that forged values in an update don't stick.
  • Use change/2, put_change/3, force_change/3, and put_assoc/4 only with server-built data, because they don't cast or filter fields.
  • Set redact: true on secret-bearing fields so struct and changeset inspection hides them; SQL logs and telemetry still carry the raw values.
  • Cast children with cast_assoc/3 or cast_embed/3 and an explicit :with changeset, after preloading only children the current user may edit. With on_replace: :delete or :delete_if_exists, any preloaded child missing from the params is deleted, so use those modes only where the user may delete every child in the set.
  • Back unsafe_validate_unique/4 with a unique index and unique_constraint/3, because the pre-check races. Give it a tenant-scoped :query when uniqueness is per tenant, or it matches other tenants' rows.
  • Bound numeric input with validate_number/3; integers already decoded from JSON reach casting at any size. On Ecto