# 03.b-operation-entity-lab

## Overview

`05.b-operation-entity-lab` is the first sample that connects an operation contract to an entity model.

It follows:

- `05-operation`
  - minimal query contract
- `05.a-operation-command-lab`
  - command contract plus job-based execution
- `05.b-operation-entity-lab`
  - query operation plus entity model in the same component

This is still a small sample.
It does not try to become a CRUD sample.
Its point is to show how a user-facing operation can sit on top of an entity-oriented domain model.

## Position

- `05-operation`
  - operation contract only
- `05.a-operation-command-lab`
  - CQRS `C` side contract and async command flow
- `05.b-operation-entity-lab`
  - CQRS `Q` side contract connected to an entity model

## Intended Use Case

Use this sample when you want to confirm:

- a component can own both an entity model and an operation service
- a query-shaped operation can expose its own typed input/output contract
- the operation layer can translate from entity-oriented data into a user-facing result contract
- operation metadata and entity metadata can coexist without turning the sample into a CRUD demo

Typical use cases are:

- teaching the boundary between application-facing operations and entity models
- showing that a query operation can return a smaller contract than the underlying entity shape
- preparing for later samples where operations and entities interact more deeply

## Files

- `src/main/cozy/operation-entity.cml`
  - the source model
- `src/main/scala/org/sample/operationentity/OperationEntitySampleFactory.scala`
  - sample-specific factory that provides the minimal executable query behavior
- `build.sbt`
  - enables `sbt-cozy` generation for the sample
- `run.sh`
  - batch wrapper for the documented shell commands

## Setup

### 1. Prepare the `cozy` command

Prepare the local `cozy` launcher that `sbt-cozy` delegates to during generation.

```bash
$ cd samples/05.b-operation-entity-lab
$ ../../bin/setup cozy
```

### 2. Build the generated sample

Compile the sample and generate the runtime classes that `cncf` will use later.

```bash
$ cd samples/05.b-operation-entity-lab
$ sbt --batch clean compile
```

## Shortcut: Run The Whole Scenario
This is the shortcut verification path, not the teaching path.
For learning, read the explicit command sequence in `Command Walkthrough` first and type those commands by hand.
`run.sh` should be treated as the batch form that replays the documented commands.

```bash
$ cd samples/05.b-operation-entity-lab
$ bash run.sh
```

`run.sh` is only a convenience batch runner. It exists so you can replay the documented command sequence after you understand it.


## Command Walkthrough

This sample uses:

```bash
cncf command ...
```

Common points:

- `cncf`:
  - the standard CNCF command-line entry point
  - in this sample repository it is invoked directly through the installed `cncf` launcher
  - after a normal CNCF installation, the same command is expected to be available as `cncf`
- `--component-factory-class ...`:
  - use the sample-specific factory that provides executable behavior for the minimal walkthrough
- `command`:
  - run one-shot CNCF command execution without starting a persistent server
- `help`:
  - ask CNCF to describe the selected component, service, or operation instead of executing it

### Operation Help

```bash
$ cncf command --component-factory-class org.sample.operationentity.OperationEntitySampleFactory help operation-entity-sample.person-app.get-person-card
```

Parameters:
- `command`
  - uses ordinary one-shot CNCF command execution for this step

- `help`
  - asks CNCF to describe the selected component, service, or operation instead of executing it

- `--component-factory-class org.sample.operationentity.OperationEntitySampleFactory`
  - uses the sample-specific factory that provides the executable query behavior
- `operation-entity-sample.person-app.get-person-card`
  - selects the generated query operation

Output example:

```yaml
type: operation
name: getPersonCard
summary: Operation: PersonApp.getPersonCard
component: OperationEntitySample
service: PersonApp
selector:
  cli: operation-entity-sample.person-app.get-person-card
returns:
  - PersonCard
```

This confirms the contract surface:

- service name: `PersonApp`
- operation name: `getPersonCard`
- output type: `PersonCard`

### Metadata Describe

```bash
$ cncf command --component-factory-class org.sample.operationentity.OperationEntitySampleFactory operation-entity-sample.meta.describe --format yaml
```

Parameters:
- `command`
  - uses ordinary one-shot CNCF command execution for this step

- `help`
  - asks CNCF to describe the selected component, service, or operation instead of executing it

- `operation-entity-sample.meta.describe`
  - invokes the generated metadata service
- `--format yaml`
  - asks for structured YAML output

Output example:

```yaml
services:
- name: PersonApp
  runtime_name: person-app
operation_definitions:
- name: getPersonCard
  kind: QUERY
  input_type: PersonLookup
  output_type: PersonCard
  input_value_kind: QUERY_VALUE
```

This confirms that the sample is still operation-oriented even though the component owns an entity model too.

### Execute The Query Operation

```bash
$ cncf command --component-factory-class org.sample.operationentity.OperationEntitySampleFactory operation-entity-sample.person-app.get-person-card --personId major-minor-entity-person-1742198400000-abcd1234
```

Parameters:
- `command`
  - uses ordinary one-shot CNCF command execution for this step

- `help`
  - asks CNCF to describe the selected component, service, or operation instead of executing it

- `operation-entity-sample.person-app.get-person-card`
  - invokes the application-facing query operation
- `--personId`
  - supplies the entity identifier accepted by `PersonLookup`

Output example:

```yaml
name: Alice
```

This is the main point of the sample:

- the input contract is entity-oriented because it takes `personId`
- the operation uses the entity model internally
- the returned contract is smaller and user-facing because it returns `PersonCard`

## What This Sample Does Not Try To Show

The sample intentionally avoids:

- full CRUD behavior
- search and paging
- job handling
- persistence-specific concerns

Those concerns belong to later samples.
