# type visibility (public / internal)

> A top-level declaration carries a public or internal visibility that decides whether code outside its package can name it. The default depends on what you declared: an entity, enum, component and control are public, a class is internal (exactly C#).

<!-- id: types-visibility · area: types · stability: stable · html: https://osysharp.com/reference/types/visibility/ -->

## Summary        {#summary}
Every top-level type has a **visibility** that decides whether code outside its package can name it. A
**`public`** type is part of the surface its package offers outward; an **`internal`** type is an
implementation detail, usable freely inside its own package — the app, or the kit — and invisible beyond it.

You rarely have to write the modifier, because the **default follows what you declared**: an `entity` or an
`enum` is public, a `class` is internal. A `component` and a `control` are public too — `internal` is how a package
keeps a helper component or a shim it only uses itself off the surface it offers.

## Signature      {#signature}
```osy syntax
entity Product { string Name; }            // public — an entity is a data surface
enum Status { Draft, Active }              // public — an enum is vocabulary
class Money { public decimal Amount; }     // internal — exactly C#

internal entity Ledger { … }               // an entity kept inside its package
public class Money { … }                   // a class offered outward
component Badge(string label) { … }        // public — a component is part of its namespace's surface
internal component Chevron() { … }         // a helper a package keeps to itself
internal control Gauge { … }               // …and the same for a foreign-ABI shim
```

## Description    {#description}

### The defaults, and why they differ   {#defaults}
| You declare | Default | Why |
|---|---|---|
| `entity` | `public` | An entity **is** the app's data surface — its fields are already public, so the type is too. |
| `enum` | `public` | An enum is vocabulary: it appears as the field type of a public entity, so an internal default would create friction at every use. |
| `class` | `internal` | Exactly C#. A class stays **source-portable** — it must lift into an external C# project verbatim, so its rules follow C#'s without deviation. |
| `component` | `public` | A component is part of what its namespace offers — which is what makes a package's components usable at all. Write `internal` for a helper you do not want callers to reach. |
| `control` | `public` | Same, for the same reason: a control's whole surface is its `control` block, so a package that could not keep a shim in would publish every one it declares. |

An explicit `public` or `internal` always overrides the default. `private` is not a top-level modifier — C# has
no private top-level types, and neither does Osy#.

### What visibility controls   {#controls}
Visibility is a **hard access rule**, not a decoration. `internal` means **the package** — exactly as C#'s means the
assembly. An `internal` type cannot be named from outside the package that declares it, and `using SomeNamespace;` of
another package brings only that namespace's **public** types into scope. This is how a published unit distinguishes
what it offers from what it merely uses.

A package is what `package.osy` declares, and an app's own source is one package too. So a kit split over several
namespaces shares its internal types, functions and members between them; inside an app, `internal` does not separate
one namespace from another; and another kit — or an app — that writes a kit's `namespace …;` line is still outside
it. The same holds for an `internal` function and an `internal` member, which is how a kit keeps a call to itself; see
[internal — a member only its own package may call](https://osysharp.com/reference/project/internal-members/).

Because an `entity` and an `enum` default to **public**, a unit that means to keep one to itself must say so:

```osy syntax
entity Product { … }             // exposed to anyone who imports this namespace
internal entity PriceHistory { … } // an implementation detail — say `internal` explicitly
```

### Visibility and authorization answer DIFFERENT questions   {#components-and-auth}
A component has both, and conflating them is the mistake worth naming. **Visibility** decides who may *reference the
declaration* — a compile-time question, about code. **Authorization** decides who may *view the rendered page* — a
runtime question, about people: a routed component requires an authenticated caller unless it is marked
`[AllowAnonymous]`, and `[Composable]` governs whether it may be rendered inside another component's surface.

So `internal component` does not mean "signed-in only", and `[AllowAnonymous]` does not make a component referenceable
from another namespace. You will usually write neither: a component is public by default and `[Composable]`/`[Route]`
carry the authorization story.

```osy syntax
// inside a package
public component Card(string title) { render { … Chevron(); … } }   // the surface
internal component Chevron() { render { … } }                      // its business
```
An app that imports that package may render `Card`; naming `Chevron` is refused, and so is
`One.Kit.Chevron(…)` — the qualified spelling reaches a namespace's surface, not past it.

### Entity fields are always public   {#entity-fields}
A visibility modifier on an **entity field** is an error — the field *is* the data, so it is always public. A
`class` member is different: it carries its own [`public`/`private`](https://osysharp.com/reference/class/constructors/) **member**
visibility, and a bare member is `private`, exactly as in C#.

## Examples       {#examples}
```osy title="what each default is, and how to override it" test app=types-visibility
/// A catalog item other code may reference. `entity` is public by default.
entity Product {
  [Required] string Name;
  decimal Price;
}

/// An internal roll-up used only inside this package — say `internal` to keep it in.
internal entity PriceHistory {
  Product Item;
  decimal Was;
}

/// A class is internal by default (C#); mark it `public` to offer it outward.
public class Money {
  public decimal Amount;
  public string Currency;
}
```

## See also       {#see-also}
- [namespace](https://osysharp.com/reference/types/namespace/) — the namespace a type lives in.
- [constructor](https://osysharp.com/reference/class/constructors/) — member visibility (`public`/`private`) on class members, the other visibility axis.
- [class methods](https://osysharp.com/reference/class/methods/) — the private-by-default rule as a builder most often hits it: a method with no modifier.
- [component](https://osysharp.com/reference/ui/component/) — the authorization axis a component also has, and why it is a different question.
- [internal — a member only its own package may call](https://osysharp.com/reference/project/internal-members/) — `internal` on a function or a member: callable only from its own package.
- [qualified element (Owner.Name.Element)](https://osysharp.com/reference/ui/qualified-element/) — naming another namespace's component or control explicitly, and what that cannot reach.
