Repository navigation
refactor: lay out both halves in FSD and share the /auth contract across them - #113
Merged
Merged
Conversation
A blank session (New Session, no input/response yet) has current set in the session snapshot AND a hidden session header, so both sign-out entries were suppressed there. The hero shell.overlay entry now shows when the current session is undefined OR still blank (byId[id].blank), hiding only for a real non-blank session (header button takes over).
Replace the stale sidebar-foot screenshots with two real captures from production: the blank new-session page (floating top-right sign-out, dsh workspace collapsed) and a real English conversation (sign-out right of the Session log). Update README.md and README.zh.md to show the new top-right placement; remove the obsolete logout-sidebar-*.png files.
dsh plugin add installs the package into the profile's node_modules; the dsh-auth bin is not added to PATH, so README and deployment docs now call it through the profile (pnpm --dir ... exec dsh-auth) and gain a Troubleshooting section. Fixes #44.
…sh-Proxy deny-list (#47) * feat(proxy): authenticated local proxy bin * feat(guard): X-Dsh-Proxy deny-list for host-native methods * docs: local proxy and deny-list deployment sections (zh+en) with systemd example * test(proxy): cover CLI parsing and upgrade header/token branches * docs: README local-proxy section and English design doc
dsh only auto-discovers project skills from .agents/skills/ (and .dsh/skills/); the skills/ directory was never picked up despite the AGENTS.md claim. Move both skills there and fix the description.
- scripts/run-gates.mjs (shared from the framework): named scenarios
derived from the verify chain; auto-detects the change surface and
runs the minimal evidence set, fail-closed to the full set
- pre-push runs npm run gates -- --base @{u} instead of only type-check
- CI: split the monolithic check job into hygiene/quality/build
parallel jobs (no path filters - full coverage always)
- docs/development.md: document gates and the new pre-push
# Conflicts: # README.zh.md # lib/client.js # lib/client.js.map # lib/client/index.d.ts # lib/client/index.d.ts.map # lib/proxy-headers.d.ts # lib/proxy-headers.d.ts.map # lib/proxy-headers.js # lib/proxy-headers.js.map # lib/proxy.d.ts.map # lib/proxy.js # lib/proxy.js.map # src/client/index.tsx # src/client/logout-action.test.tsx # src/proxy-headers.test.ts # src/proxy-headers.ts # src/proxy.ts
… into verify chain and CI
…tructure docs and README
refactor: layered src with barrels + framework verify gates + decision records
… accidental main commits)
…lay guard, user totp CLI)
The wrapServer disposer used to clear the route tables and write back a snapshot taken at wrap time. Reloading dsh-auth-gate alone (a config change in the Plugins page) therefore dropped routes other plugins had registered after the wrap, resurrected routes whose owner had been disposed, and made that owner's next load throw "duplicate exact route". Unwrap now swaps an entry back to its original handler only while it still holds a guard this wrap produced (tracked in per-wrap WeakMaps). Deleted entries stay deleted, foreign replacements are left alone, and post-wrap routes survive with the guard removed. Adds a real cordis + webserver reload repro and per-entry unit tests, records the change as decision D27 (superseding impl-m1 D6's snapshot clause), and updates the code-review skill rule that asked for an exact pre-wrap restore.
`engines.dsh` and the `@deepseek-ai/dsh-storage-domain` peer both end in `>=0.2.0-rc.1` now; the three caret alternatives stay as the record of the host lines that were actually verified. A hand-added alternative always lags a dsh release, and a rejected bundle is skipped silently, so the login gate would disappear rather than fail loudly. The guard test now asserts the floor covers every later host version, and the readme, specs and D27 record the trade-off. No source change (D27).
…rollback) Brings in the guard unwrap rollback fix (#107) and the 0.17.1 release. That fix's decision record already holds D27, so the corridor-floor record written on 2026-10-07 is renumbered D28 and its references follow.
The host half moves into src/host/ with FSD's lower three layers (shared, entities, features) and the client half takes the five-layer layout, both checked by Steiger, matching dsh-lingualab. Entries and assembly stay at the src/ root; integration tests move to test/. Once implemented it supersedes the directory parts of D5 and D11.
The build never emptied lib/, so outputs of moved or deleted sources stayed tracked (lib/features/session/, lib/skill-install.*), and the CI parity diff cannot see leftovers. scripts/clean-lib.mjs now removes lib/ first; the rebuild deletes 36 stale or test-only files. tsconfig.build.json excludes only *.test.ts, so test helpers under src/ were compiled into lib/ and shipped. The 14 integration tests and their 4 helpers move to test/integration/, and the admin and password-login harnesses move to test/ beside the existing ones. Vitest, ESLint, run-gates, the slice-check whitelist, the development docs and the bundled skills follow the new paths. Step 1 of the D29 plan.
Move src/client into shared, entities/account, four features (change-password, admin-users, logout, nav-icon) and the account-section widget, each slice behind an index.ts barrel. index.tsx stays at the client root; there is no pages or app layer. lint:fsd now runs Steiger over both halves, and slice:check only accepts client files under the five layer folders plus index.tsx and its test. lib/ is rebuilt from the new layout.
Move D29 to implemented/ with its text describing the landed layout and register it in docs/decisions.md. D5 (layered src with barrels) and D11 (HTTP endpoint layer) are superseded by D29 and move to archived/ unchanged; their hashes seed archived/.manifest.json. D9 stays implemented because its injection rule still applies. The old src-refactor-plan docs gain a note that D29 supersedes them.
tsconfig.client.build.json excluded only *.test.tsx, so the five client *.test.ts files emitted .d.ts and .d.ts.map into lib/client/ and shipped with the package. Exclude *.test.ts as well. bundle:check now fails if any *.test.* or *.spec.* file appears anywhere under lib/, so the leak cannot come back unnoticed.
A top-level GET that arrives cross-site (Sec-Fetch-Site: cross-site, Sec-Fetch-Dest: document) carries the gate's Lax cookie but not dsh's SameSite=Strict session cookie, so dsh answered 401 and a reload kept the cross-site context. For requests the gate allows, serve a static bounce page that re-navigates via location.replace(location.href); the retry is same-origin, so the Strict cookie is sent and the bounce cannot loop.
…resh-issue-fd5fc5
development's D29 (cross-site navigation bounce) shipped first, so the FSD layering record is renumbered to D30. cross-site-bounce moves into src/host/shared/guard/ and its integration test into test/integration/.
The route paths, the password-changed notice key and the URLs built from them were written more than twenty times across both halves, with two separate LOGIN_PATH definitions on the host side. src/protocol/index.ts now defines them once (pure constants and functions, no imports). The host enters through src/host/shared/protocol/ and the client through src/client/shared/api/protocol.ts. slice:check allows only those two bridges to import the contract. The p11 source pin for the client redirect now asserts that the client uses the contract constant instead of comparing literals. Records D31 and updates the structure docs.
scripts/check-host.mjs checks what the dsh host relies on and no type checker sees: the package name, the cordis.patch.yml Loader row, the client registration id and the host entry name agree; every manifest target exists after a build; every require() in lib/client.js and every CLIENT_EXTERNALS entry is a module the shell seeds (mirrors dsh PLATFORM_MODULES, logged as debt in .rsp/TechDebt.md); no route literal lives outside src/protocol, every registration names a protocol constant, every protocol path is registered, and every route the READMEs mention exists. --self-test runs eighteen broken fixture trees, one per rule, and fails if any of them passes. The gate runs in verify after bundle:check, in the CI build job and in the build scenario of run-gates.
Extend the D31 cross-half contract from route paths to the request, response and error bodies of the /auth endpoints. src/protocol/payloads.ts holds them as pure types (StatusResponse, AdminUserRow, UsersResponse, the password-change and admin-reset request/response/error bodies, UserRole, SessionKind, PasswordRule, Unchecked<T>), re-exported by src/protocol/index.ts and reached through the two existing bridges. Host: the status, users, reset and password-change writers are typed with the contract bodies; form fields are read through the typed formField<Request>() helper; the user and session entities take UserRole, SessionKind and PasswordRule from shared/protocol, so no @x import is needed. Client: the hand-written admin-types.ts mirror is deleted. AccountStatusView derives from StatusResponse, AdminUserRow comes from shared/api, form and result types move to features/admin-users/model, request bodies are built from contract-typed objects via encodeForm, and parsers read keys through Unchecked<T>. Runtime behaviour is unchanged. Docs: D31 records, the decisions index, the D30 placement table and docs/specs/development(_zh).md describe the payload half.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes
developmenttomain. No user-facing behaviour changes: routes, cookies, pages and config are the same.What changes
D30, FSD layout. The host half moves into
src/host/{shared,entities,features}and the client half intosrc/client/{shared,entities,features,widgets}. Both halves are checked by Steiger (npm run lint:fsd). Integration tests move totest/integration/. Client test declarations no longer ship inlib/, andlib/is emptied before each build.D31, cross-half contract. The
/auth/*paths, thepassword-changednotice key, the login/logout URL builders and the endpoint payload types are defined once insrc/protocol/. Each half reaches the contract through a single bridge, andslice:checkenforces that. More than twenty route literals and the client's hand-written payload mirror are gone.npm run host:check. A new gate covering what the dsh host relies on and no type checker sees:nameagree;requires modules the shell seeds;src/protocol, every protocol path is registered, and every README route exists.--self-testrejects 18 broken trees. The gate runs inverify, in the CI build job and inrun-gates.The FSD decision is renumbered D29 → D30, because the cross-site bounce (fix(gate): bounce cross-site navigations so dsh's Strict cookie is sent #111) shipped first as D29.
Release
The squash title is
refactor:, which release-please does not release on its own. When merging I will add aRelease-As: 0.17.4footer so that this ships as a patch.Verification
npm run verifypasses locally: format, lint, no-emdash, slice, Steiger, lock, decisions, docs, readme parity, type-check, 1077 tests with coverage, build, bundle check and host:check.