ADORSYS-GIS / ADORSYS-GIS/converse-frontends

[Story]: every workspace package is typechecked under its own tsconfig, not incidentally via apps/console

オープン
#434 コメント 0 件 リアクション 0 件 担当者 1 名 @benie-joy-possi が担当を希望しています GitHub で見る
user-story
主要言語
TypeScript
スター
0
フォーク
0
平均マージ
1時間 49分
マージ済み PR(30日)
253

説明

## Story Statement

As a developer changing a shared workspace package (`authz-rpc`, `hooks`, `api-rest`, `i18n`, `api-native`),
I want CI to typecheck that package under its own `tsconfig.json`,
so that a type error in it fails the PR that introduced it, instead of surfacing later — or never.

## Real Intent

The Typecheck job in `.github/workflows/test.yml` discovers work by globbing `tsconfig.json` at `-maxdepth 2` under `apps/` and `packages/`. **Only 4 of 10 workspaces have one** (`apps/authz-ui`, `apps/console`, `packages/chart-core`, `packages/ui-web`), so five packages are never checked under their own compiler settings.

The job's author clearly cared about this gate not being hollow — it carries an explicit no-op guard:

```
if [ "${#tsconfigs[@]}" -eq 0 ]; then
echo "::error::No tsconfig.json found under apps/ or packages/ — the typecheck gate would be a no-op"
```

That guard fires only when the count is **zero**. It cannot notice that the count is 4 when it should be 9, which is the actual state today. This is the "green does not mean tested" failure mode: the job passes having never looked at most of the packages.

Found while upgrading cratestack 0.9.4 → 0.10.0 (#433). That PR regenerated `packages/authz-rpc`'s client and changed its emitted peer bounds — and `packages/authz-rpc` is one of the packages with no `tsconfig.json` of its own.

## Background and Context

The coverage is **partial, not absent** — worth stating precisely so this isn't over- or under-sold:

| Package | src files | Coverage today |
|---|---|---|
| `packages/hooks` | 34 | Incidental only — via `apps/console`'s import graph |
| `packages/api-rest` | 20 | Incidental only — via `apps/console` |
| `packages/authz-rpc` | 9 | Incidental only — via `apps/console` |
| `packages/i18n` | 3 | **None** — not a dependency of either app |
| `packages/api-native` | 1 | **None** — not a dependency of either app |

The three "incidental" packages set `"main"`/`"types"` to `src/index.ts`, so `apps/console`'s `tsc --noEmit` does follow into their real source. That is genuine coverage, and it is why this is a gap rather than an outage. What it does **not** cover:

- Code not reachable from `index.ts` — including every `*.test.ts` in those packages, and `authz-rpc`'s separate `./refine` export unless console happens to import it.
- The package's **own** compiler settings. They are checked under `apps/console`'s Next.js config (its `strict`, `lib`, `jsx`, `types`), not their own. A package intending stricter settings than console's silently doesn't get them.
- `apps/authz-ui` depends only on `@lightbridge/ui-web`, so it contributes no coverage here.

## Source of truth (links)

- Observed during #433 (cratestack 0.9.4 → 0.10.0), which regenerated `packages/authz-rpc`'s client — a package outside the gate.
- `.github/workflows/test.yml`, the `Typecheck all workspaces` step and its zero-count no-op guard.
- Estate rule that a gate which can pass without running is not a gate (the same reasoning behind lightbridge-authz's `just it-tests` `check_binary` guards, which assert a non-zero test count because "a skip is not a pass").

## Acceptance Criteria

### Functional
- [ ] Given a workspace package under `apps/` or `packages/` containing TS source, when CI runs Typecheck, then that package is checked under **its own** `tsconfig.json`.
- [ ] Given a type error introduced in `packages/hooks`, `packages/api-rest`, `packages/authz-rpc`, `packages/i18n` or `packages/api-native`, when CI runs, then the Typecheck job **fails**.
- [ ] Given a type error only in a package's `*.test.ts`, when CI runs, then it is still caught.

### Negative / Edge Cases
- [ ] Given a **new** workspace package added with no `tsconfig.json`, when CI runs, then the job **fails loudly** rather than silently skipping it. (This is the real defect — the guard must detect "fewer tsconfigs than packages with TS source", not just "zero".)
- [ ] Given `packages/authz-rpc/generated/` (gitignored, regenerated by `postinstall`), when CI runs, then it stays excluded — it has its own `tsconfig.json` and is not hand-maintained.
- [ ] Given a package intentionally without TS source, when CI runs, then it does not fail the new guard.

### Non-Functional
- [ ] Typecheck job wall-clock stays within roughly 2× today's ~1 min; if adding five projects costs more, consider TS project references / `--build` with incremental caching.
- [ ] Prove the gate works: introduce a deliberate type error in each newly-covered package, confirm CI goes red **for that reason**, then revert. A gate added without watching it fail has not been verified.

## Out of Scope

- Fixing whatever type errors the new coverage surfaces — if the backlog is non-trivial, split into a follow-up per package.
- The 2 pre-existing `pnpm lint` errors on `main` (`react-hooks/rules-of-hooks` in `apps/console/src/client/use-shared-mutation.test.tsx`; setState-in-effect in `apps/console/src/containers/use-rename-account-dialog.ts`). Related smell, separate story.
- Changing any package's public entrypoints or build outputs.

## Dependencies and Blockers

None. Self-contained CI + tsconfig work.

## Assumptions

- Each of the five packages *should* be typechecked. If `api-native` is dead code from the Expo retirement (#279), deleting it is a legitimate alternative to adding a tsconfig — decide before implementing.
- A shared `tsconfig.base.json` that packages extend is preferable to five hand-rolled configs. Confirm against how `packages/ui-web` and `packages/chart-core` configure themselves today.

## Implementation Notes

Guidance, not gospel:

1. Add a `tsconfig.json` per package, extending a shared base, with `noEmit` for check-only packages.
2. Replace the zero-count guard with a real completeness check: enumerate packages containing `src/**/*.ts(x)`, assert each has a discoverable `tsconfig.json`, and fail listing the missing ones. That is the part which keeps this from regressing the next time a package is added.
3. Consider `tsc --build` with project references so the five new projects reuse each other's output instead of recompiling per invocation.

## Test Expectations

- CI: the Typecheck job covers 9 projects (or whatever the true count is), not 4.
- Regression: the completeness guard fails when a package with TS source lacks a tsconfig — verified by temporarily removing one.
- Mutation-style: a deliberate type error in each newly-covered package turns CI red, then is reverted.

## Verification evidence

Evidence the gap is real, gathered on 2026-08-31 against `main`:

```bash
$ for d in apps/*/ packages/*/; do [ -f "$d/tsconfig.json" ] || echo "NO tsconfig: $d"; done
NO tsconfig: packages/api-native/
NO tsconfig: packages/api-rest/
NO tsconfig: packages/authz-rpc/
NO tsconfig: packages/hooks/
NO tsconfig: packages/i18n/

$ find packages/authz-rpc -name tsconfig.json -not -path "*/node_modules/*"
packages/authz-rpc/generated/tsconfig.json # excluded by the CI loop's -not -path '*/generated/*'
```

Running CI's exact discovery loop locally yields **4** tsconfigs and `TYPECHECK_STATUS=0` — green, having never checked five packages under their own settings.

Not yet verified (for the implementer): how many type errors the new coverage actually surfaces.

## Human accountable owner

@stephane-segning

## AI Usage Declaration

Drafting this story, Refining acceptance criteria, Suggesting implementation.

Drafted by Claude Opus 5 (Claude Code) after observing the gap while upgrading cratestack in #433. All command output quoted above is from real runs against `main`.

## Human verification completed

- [ ] I checked the story against the source of truth
- [ ] I confirmed the acceptance criteria
- [ ] I reviewed the implementation approach
- [ ] I am the accountable owner and accept responsibility for this story.

**Left unticked deliberately** — these are the accountable owner's assertions to make, not the drafting agent's.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。