# `Bylaw.Credo.Check.Ecto.ContextOwnsSchemaQueries`
[🔗](https://github.com/ryanzidago/bylaw/blob/v0.4.0/lib/bylaw/credo/check/ecto/context_owns_schema_queries.ex#L1)

## Basics

> #### This check is disabled by default. {: .neutral}
>
> [Learn how to enable it](`e:credo:config_file.html#checks`) via `.credo.exs`.

This check has a base priority of `higher` and works with any version of Elixir.

## Explanation

Only configured Phoenix context boundary modules may write Ecto queries for
schemas owned by their namespace.

Keeping schema queries behind their owning context gives the application one
place to enforce authorization, visibility, and loading rules. It also keeps
controllers, jobs, and neighboring contexts from coupling themselves to the
schema's persistence details.

## Examples

Configure the context boundary modules that own schemas below their namespace:

```elixir
{Bylaw.Credo.Check.Ecto.ContextOwnsSchemaQueries,
 [
   contexts: [
     MyApp.Conversations,
     MyApp.Branches,
     MyApp.Runs
   ]
 ]}
```

Avoid outside `MyApp.Conversations`:

      from(c in Conversation, where: c.id == ^id)
      Conversation |> where([c], c.visible)
      Repo.get_by(Conversation, slug: slug)
      Repo.insert(%Conversation{})

Prefer:

      MyApp.Conversations.fetch_conversation(id)

Plain schema references are allowed. This check is specifically about
writing Ecto query or direct Repo CRUD logic for a schema owned by another
configured context namespace.

## Notes

A schema module is owned by the longest configured context prefix when the
schema starts with that context plus one or more extra module segments.
For example, `MyApp.Conversations.Message` is owned by
`MyApp.Conversations`.

Nested modules under a context are not treated as owners by default. Only the
exact configured context module may write queries for schemas under that
namespace.

This check uses static AST analysis, so it favors clear source-level patterns
over runtime behavior.

## Options

Configure options in `.credo.exs` with the check tuple:

```elixir
%{
  configs: [
    %{
      name: "default",
      checks: [
        {Bylaw.Credo.Check.Ecto.ContextOwnsSchemaQueries,
         [
           contexts: [MyApp.Conversations],
           excluded_modules: [MyApp.Legacy.ReportBuilder],
           excluded_paths: ["lib/my_app/generated/"],
           repo_modules: [MyApp.Repo]
         ]}
      ]
    }
  ]
}
```

- `:contexts` - Context boundary modules that own schemas below their namespace.
- `:excluded_modules` - Modules allowed to write queries for owned schemas.
- `:excluded_paths` - Paths containing any configured string are skipped.
- `:repo_modules` - Repo modules to inspect. When empty, any module whose last segment is `Repo` is treated as a Repo.
- `:allow_owner_descendants` - When `true`, modules nested under the owner context may also write queries. Defaults to `false`.

## Check-Specific Parameters

Use the following parameters to configure this check:

### `:contexts`

  Context boundary modules that own schemas below their namespace.

*This parameter defaults to* `[]`.

### `:excluded_modules`

  Modules allowed to write queries for owned schemas.

*This parameter defaults to* `[]`.

### `:excluded_paths`

  Paths containing any configured string are skipped.

*This parameter defaults to* `[]`.

### `:repo_modules`

  Repo modules to inspect. When empty, any module whose last segment is Repo is treated as a Repo.

*This parameter defaults to* `[]`.

### `:allow_owner_descendants`

  When true, modules nested under the owner context may also write queries.

*This parameter defaults to* `false`.

## General Parameters

Like with all checks, [general params](`e:credo:check_params.html`) can be applied.

Parameters can be configured via the [`.credo.exs` config file](`e:credo:config_file.html`).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
