Skip to content

feat(squads): bounded contexts + ADRs for onboarding & squads governance#332

Open
danielhe4rt wants to merge 14 commits into
4.xfrom
feat/onboarding-squads
Open

feat(squads): bounded contexts + ADRs for onboarding & squads governance#332
danielhe4rt wants to merge 14 commits into
4.xfrom
feat/onboarding-squads

Conversation

@danielhe4rt

@danielhe4rt danielhe4rt commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Artefato de fluxo de tasks

O quê

Estabelece dois novos bounded contextsonboarding (camada de Entrada) e squads (Governança) — via scaffold dos módulos + documentação de domínio (CONTEXT.md + ADRs). Sem código de runtime ainda — é a fundação de design que destrava a implementação.

Resultado de uma sessão /grill-with-docs sobre o Mapa de Fluxos dos Squads (camadas Entrada + Governança; o Núcleo do jogo fica de fora por enquanto).

Decisões principais (ver ADRs)

Onboarding (Entrada)

  • ADR-0001 — Onboarding polimórfico por tipo (OnboardingType → handler(), mesmo idioma do IdentityProvider::getClient). Modelo onboarding + tabela onboarding_steps (auditoria por etapa). Cadeia de pré-requisitos entre tipos (Welcome é pré-req de Squads). "APTO" = Squads onboarding concluído.
  • ADR-0002 — Sinal de "PR aprovado" via novo evento de domínio GithubPullRequestApproved do integration-github (transporte continua centralizado; HMAC/dedup reusados). Repo de desafio via GithubRepository.purpose = challenge. Vínculo do GitHub é gate → sem reconciliação (diverge do BDD original da P.O.).

Squads (Governança)

  • ADR-0001 — Governança como record-keeping, não workflow engine. Eleição/remoção/saída/realocação rodam off-system; o módulo registra o resultado. Candidatura é o único fluxo conduzido. Autoridade = super-admins (config('he4rt.admins')) + capitão gere o próprio squad.
  • ADR-0002 — Modelo de dados: squads, squad_members (pivot com role), squad_membership_events (append-only), squad_applications. Capitão derivado do pivot (sem captain_id). Capitão único + exclusividade "1 squad ativo" garantidos no banco (partial unique) + validação na Action.

Fora de escopo (regras humanas, aplicadas off-system)

Elegibilidade "≥1 entrega", desempate pelo Head, candidatura única, mínimo de votos proporcional, "sem reeleição direta". Só o resultado é registrado — por isso o ponto aberto "definição de entrega" não bloqueia.

Arquivos

  • CONTEXT-MAP.md — registra os dois contextos + regras de dependência
  • app-modules/onboarding/ — scaffold + CONTEXT.md + 2 ADRs
  • app-modules/squads/ — scaffold + CONTEXT.md + 2 ADRs

Follow-ups (não neste PR)

  • Implementação: migrations, models (com PHPDoc), enums, Actions, Policy, listener do GithubPullRequestApproved, campo GithubRepository.purpose
  • Mover *ServiceProvider de src/Providers/src/ (guideline .ai/02-module-architecture)
  • Atualizar o documento da P.O. (cenário de reconciliação removido)

@stherzada stherzada left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avalie as considerações, e me dê um toque.

Comment thread app-modules/onboarding/docs/adr/0001-onboarding-polimorfico-por-tipo.md Outdated
Comment thread app-modules/onboarding/CONTEXT.md
Comment thread app-modules/onboarding/CONTEXT.md
Comment thread app-modules/squads/docs/adr/0001-governanca-como-registro.md

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No geral não entendi quais decisões ele viu de problema, necessito de mais contexto para atuar nesse review.

Comment thread app-modules/squads/CONTEXT.md
@Clintonrocha98

Copy link
Copy Markdown
Member

up!

1 similar comment
@stherzada

Copy link
Copy Markdown

up!

Co-authored-by: Sther <72408918+stherzada@users.noreply.github.com>
Signed-off-by: Daniel Reis <danielhe4rt@gmail.com>
@stherzada

Copy link
Copy Markdown

Comentário do Elves:

Tenho apenas duas observações:

  1. No squad_members com role no pivot, o papel de capitão está garantido pela partial unique constraint, o que faz sentido. Talvez valha considerar também a geração de um evento em squad_membership_events quando houver troca de capitão, para manter a trilha de auditoria consistente com o restante do modelo.
  2. O GithubPullRequestApproved, que vem do módulo de integração com o GitHub, será disparado por webhook ou por polling?

@danielhe4rt

Copy link
Copy Markdown
Contributor Author
  1. No squad_members com role no pivot, o papel de capitão está garantido pela partial unique constraint, o que faz sentido. Talvez valha considerar também a geração de um evento em squad_membership_events quando houver troca de capitão, para manter a trilha de auditoria consistente com o restante do modelo.

R: Faz sentido capturar qualquer evento de uma squad. Por mais simples que seja, é o que precisamos no momento.

  1. O GithubPullRequestApproved, que vem do módulo de integração com o GitHub, será disparado por webhook ou por polling?

R: Ambos serão o mesmo payload, no final, o meio não importa desde que tenha a Action fazendo essa fronteira entre o Transporter;

stherzada
stherzada previously approved these changes Jun 21, 2026

@stherzada stherzada left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Só não esquece de mandar o a doc lá!

Comment thread composer.json
| `completed_at` | timestamptz? | |
| timestamps | tz | |
| UNIQUE | `(onboarding_id, step_key)` | |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pra fins de auditoria de transicionamento e checks mais rapidos, nao valeria armazenar a transição de steps com uma coluna de previously_at? traria ganho pra disciplina de transition mencionada na linha 102

ou eles foram desenhados pra serem "ever-forward" (flow nao é um grafo direcionado, apenas guarda estados)?

PR do candidato** num repo de desafio. A plataforma precisa reagir a essa aprovação.

O `integration-github` já é o **único** ponto que fala com o GitHub: `GithubWebhookController` recebe
todos os webhooks, grava no `GithubEventLog` (lake, dedup por `delivery_id`), e o `ProjectGithubEvent`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

estamos distinguindo repositório de projeto ou ambas palavras se referem à mesma coisa? um evento emitido por um repositorio deveria RepoGithubEvent ou ProjectGithubEvent como é agora?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

por que os CONTEXT.md estão em inglês e os ADRs não? pra fins de linguagem ubiqua, não deveria serem todos no mesmo idioma?

consulta interna do `integration-github`) e furaria o encapsulamento do lake. Descartado.
- **Config de repo de desafio dentro do `onboarding`** (em vez do `purpose` na allowlist): manteria o
`integration-github` sem nenhuma categoria nova, mas duplicaria o cadastro de repos e perderia o
benefício de excluir o repo de desafio da projeção de contribuições num lugar só. Trade-off aceito

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

com o purpose acoplamos a entidade do GithubRepository no dominio de onboarding. cada type nao poderia ter um repo (unique key) como repo challenge apenas apontando pro repo (1:1)*? isso ainda permitiria excluir os repos de challenge das contribuições

*1 type aponta para 1 repo de challenge

| **OnboardingFlow** | The per-type handler (a class behind the `OnboardingFlow` contract). Declares `steps()`, `prerequisites()`, `advance()`, `isComplete()`. All type-specific rules live here. | The model — the Flow is stateless behaviour; the Onboarding is the state |
| **OnboardingStep** | One auditable stage of a flow, one row in `onboarding_steps`. Carries its own `status` + `data` (jsonb) + `completed_at`. Enables pause/resume and history. | A prerequisite (another _type_ that must be complete first) |
| **Prerequisite** | Another `OnboardingType` that must be **completed** before this one can start (e.g. `Squads` requires `Welcome`). Declared by the flow, enforced on start. | A step (intra-type) — a prerequisite is inter-type |
| **APTO** | Domain shorthand for "completed the `Squads` onboarding". The condition that unlocks squad candidacy and squad creation. It is _not_ a global flag — it is `Squads` completion. | A generic "active member" — APTO is specifically squad-eligible |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APTO ta amarrado ao contexto do onboarding de Squads ou pretendemos reutilizar esse shorthand pra futuros onboarding types? se pretendemos reutilizar acho bom ja desamarrarmos os conceitos

### Modelo

- `squads` (`status`: `draft`/`active`/`inactive`/`archived`, `objective`, `slug`, tenant-scoped).
- `squad_members` (pivot): `role` (`Captain`/`SubCaptain`/`Member`/`ExMember`), `joined_at`, `left_at`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sailor (marujo) ao inves de Member se quiserem que o schema esteja bem aderido ao tema de piratas, xd

### `squads`

`name`, `slug`, `objective` (text, nullable — `draft` pode não ter), `status` (`SquadStatus`
`draft`/`active`/`inactive`/`archived`, default `draft`), timestamps.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created_by pra auxiliar a encontrar o autor do squad no futuro (utilidade)

@gvieira18 gvieira18 force-pushed the feat/onboarding-squads branch from 3079a6f to 36262a8 Compare June 30, 2026 00:26
@gvieira18 gvieira18 marked this pull request as ready for review June 30, 2026 00:26
@gvieira18 gvieira18 requested a review from a team June 30, 2026 00:26
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: b9d6418b-0fe7-481b-8bda-1203f6e135c7

📥 Commits

Reviewing files that changed from the base of the PR and between 36262a8 and 95be88d.

⛔ Files ignored due to path filters (2)
  • composer.lock is excluded by !**/*.lock
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • composer.json
  • package.json

📝 Walkthrough

Walkthrough

Two new app-modules are added: onboarding and squads. Each gets package metadata, PSR-4 autoloading, PHPStan config, and a Laravel service provider. onboarding adds context documentation and two ADRs for polymorphic flows and GitHub approval event handling. squads adds context documentation and two ADRs for governance record-keeping and the data model. CONTEXT-MAP.md is updated with Squads and cross-module dependency rules, and the root composer.json requires both packages.

Possibly related issues

Suggested reviewers

  • Clintonrocha98
  • gvieira18
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the new onboarding and squads bounded-context scaffolding plus ADR/documentation work.
Description check ✅ Passed The description is directly aligned with the PR’s onboarding/squads context-map, scaffolding, and ADR changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (6)
composer.json (2)

32-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent version constraint.

Other he4rt/* packages use >=1 or ^1.1; * is looser and inconsistent. Align with >=1 unless path-repo semantics require otherwise.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composer.json` at line 32, The dependency constraint for he4rt/onboarding is
too loose and inconsistent with the other he4rt/* packages. Update the
composer.json requirement for he4rt/onboarding to match the existing versioning
style used by the other package entries (preferably >=1, unless the repository
setup truly requires *), so the package constraints stay aligned.

37-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent version constraint.

Same as above for he4rt/squads.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composer.json` at line 37, The dependency constraint for he4rt/squads is
inconsistent with the other packages in composer.json; update its version
requirement to match the same fixed constraint pattern used nearby instead of
using a wildcard. Locate the he4rt/squads entry in composer.json and align it
with the surrounding dependency versions so the package list stays consistent.
app-modules/onboarding/composer.json (2)

5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove hardcoded version.

Path repositories with * constraint don't need a version; Composer derives it from VCS or uses 1.1.0 fallback. Hardcoding creates maintenance churn.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app-modules/onboarding/composer.json` at line 5, Remove the hardcoded version
from the onboarding Composer manifest; the package should rely on the path
repository/VCS-derived version instead of the current fixed value. Update the
composer.json entry so the package metadata no longer declares a manual version,
keeping the manifest aligned with Composer’s version inference behavior.

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a description.

Empty description field.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app-modules/onboarding/composer.json` at line 3, The composer.json for the
onboarding module has an empty description field and needs a meaningful package
description. Update the description value in the manifest so it briefly explains
the purpose of the onboarding module, keeping it aligned with the module name
and existing package metadata.
app-modules/onboarding/CONTEXT.md (2)

41-50: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add text language to fenced block.

Same as above for the directory structure block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app-modules/onboarding/CONTEXT.md` around lines 41 - 50, The directory
structure example in CONTEXT.md uses a fenced block without a language, so
update that block to use text syntax highlighting like the other fenced example.
Locate the markdown fence around the `src/` tree in the onboarding context doc
and change it to a text-labeled code block while keeping the content unchanged.

26-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add text language to fenced block.

markdownlint flags missing language. Use text for the ASCII diagram.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app-modules/onboarding/CONTEXT.md` around lines 26 - 35, The fenced ASCII
diagram in CONTEXT.md is missing a language tag, which triggers markdownlint.
Update the fenced block around the onboarding flow diagram to use text as the
fence language so the block is explicitly marked as plain text.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app-modules/onboarding/composer.json`:
- Line 5: Remove the hardcoded version from the onboarding Composer manifest;
the package should rely on the path repository/VCS-derived version instead of
the current fixed value. Update the composer.json entry so the package metadata
no longer declares a manual version, keeping the manifest aligned with
Composer’s version inference behavior.
- Line 3: The composer.json for the onboarding module has an empty description
field and needs a meaningful package description. Update the description value
in the manifest so it briefly explains the purpose of the onboarding module,
keeping it aligned with the module name and existing package metadata.

In `@app-modules/onboarding/CONTEXT.md`:
- Around line 41-50: The directory structure example in CONTEXT.md uses a fenced
block without a language, so update that block to use text syntax highlighting
like the other fenced example. Locate the markdown fence around the `src/` tree
in the onboarding context doc and change it to a text-labeled code block while
keeping the content unchanged.
- Around line 26-35: The fenced ASCII diagram in CONTEXT.md is missing a
language tag, which triggers markdownlint. Update the fenced block around the
onboarding flow diagram to use text as the fence language so the block is
explicitly marked as plain text.

In `@composer.json`:
- Line 32: The dependency constraint for he4rt/onboarding is too loose and
inconsistent with the other he4rt/* packages. Update the composer.json
requirement for he4rt/onboarding to match the existing versioning style used by
the other package entries (preferably >=1, unless the repository setup truly
requires *), so the package constraints stay aligned.
- Line 37: The dependency constraint for he4rt/squads is inconsistent with the
other packages in composer.json; update its version requirement to match the
same fixed constraint pattern used nearby instead of using a wildcard. Locate
the he4rt/squads entry in composer.json and align it with the surrounding
dependency versions so the package list stays consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 6b3001fb-8800-43c2-b335-94e1d1223642

📥 Commits

Reviewing files that changed from the base of the PR and between 794ce39 and 36262a8.

📒 Files selected for processing (26)
  • CONTEXT-MAP.md
  • app-modules/onboarding/CONTEXT.md
  • app-modules/onboarding/composer.json
  • app-modules/onboarding/database/factories/.gitkeep
  • app-modules/onboarding/database/migrations/.gitkeep
  • app-modules/onboarding/database/seeders/.gitkeep
  • app-modules/onboarding/docs/adr/0001-onboarding-polimorfico-por-tipo.md
  • app-modules/onboarding/docs/adr/0002-sinal-de-pr-aprovado-via-evento-de-dominio.md
  • app-modules/onboarding/phpstan.ignore.neon
  • app-modules/onboarding/phpstan.neon
  • app-modules/onboarding/src/Providers/OnboardingServiceProvider.php
  • app-modules/onboarding/tests/Feature/.gitkeep
  • app-modules/onboarding/tests/Unit/.gitkeep
  • app-modules/squads/CONTEXT.md
  • app-modules/squads/composer.json
  • app-modules/squads/database/factories/.gitkeep
  • app-modules/squads/database/migrations/.gitkeep
  • app-modules/squads/database/seeders/.gitkeep
  • app-modules/squads/docs/adr/0001-governanca-como-registro.md
  • app-modules/squads/docs/adr/0002-modelo-de-dados.md
  • app-modules/squads/phpstan.ignore.neon
  • app-modules/squads/phpstan.neon
  • app-modules/squads/src/Providers/SquadsServiceProvider.php
  • app-modules/squads/tests/Feature/.gitkeep
  • app-modules/squads/tests/Unit/.gitkeep
  • composer.json

Bump guzzle to ^7.13.1 and refresh transitive locks; normalize
he4rt/onboarding and he4rt/squads constraints from "*" to ">=1"
to match sibling path modules.
Update tailwindcss/vite to 4.3.2, prettier to 3.9.3,
npm-check-updates to 22.2.9.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants