@things-factory/worklist 10.1.208 → 10.1.209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/components/timeline-entries.js +2 -1
- package/dist-client/components/timeline-entries.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-view.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.js +36 -12
- package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.js +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.d.ts +1 -2
- package/dist-client/pages/todo/draft-list-page.js +11 -14
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-approval/check-authority.d.ts +2 -13
- package/dist-server/controllers/activity-approval/check-authority.js +2 -49
- package/dist-server/controllers/activity-approval/check-authority.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegate.js +1 -8
- package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegation.d.ts +5 -15
- package/dist-server/controllers/activity-approval/delegation.js +2 -16
- package/dist-server/controllers/activity-approval/delegation.js.map +1 -1
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.d.ts +2 -2
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js +1 -1
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js.map +1 -1
- package/dist-server/controllers/activity-approval/seat-standing.d.ts +66 -0
- package/dist-server/controllers/activity-approval/seat-standing.js +57 -0
- package/dist-server/controllers/activity-approval/seat-standing.js.map +1 -0
- package/dist-server/controllers/activity-instance/issue.js +9 -15
- package/dist-server/controllers/activity-instance/issue.js.map +1 -1
- package/dist-server/controllers/activity-thread/abort.js +7 -0
- package/dist-server/controllers/activity-thread/abort.js.map +1 -1
- package/dist-server/controllers/activity-thread/restart.js +4 -2
- package/dist-server/controllers/activity-thread/restart.js.map +1 -1
- package/dist-server/controllers/activity-thread/submit.js +5 -1
- package/dist-server/controllers/activity-thread/submit.js.map +1 -1
- package/dist-server/controllers/common.js +1 -1
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/service/activity/index.d.ts +2 -2
- package/dist-server/service/activity-approval/index.d.ts +1 -1
- package/dist-server/service/activity-approval/my-pending-approvals.d.ts +5 -5
- package/dist-server/service/activity-approval/my-pending-approvals.js +5 -8
- package/dist-server/service/activity-approval/my-pending-approvals.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.d.ts +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +9 -4
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/index.d.ts +1 -1
- package/dist-server/service/activity-instance/request-box.d.ts +2 -0
- package/dist-server/service/activity-instance/request-box.js +18 -0
- package/dist-server/service/activity-instance/request-box.js.map +1 -0
- package/dist-server/service/activity-summary/activity-summary-query.js +3 -3
- package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
- package/dist-server/service/activity-summary/index.d.ts +1 -1
- package/dist-server/service/activity-template/index.d.ts +2 -2
- package/dist-server/service/activity-thread/index.d.ts +1 -1
- package/dist-server/service/activity-thread/my-open-threads.d.ts +1 -2
- package/dist-server/service/activity-thread/my-open-threads.js +2 -3
- package/dist-server/service/activity-thread/my-open-threads.js.map +1 -1
- package/dist-server/service/index.d.ts +3 -3
- package/dist-server/service/subscription/subscription-filters.d.ts +2 -2
- package/dist-server/service/subscription/subscription-filters.js +2 -2
- package/dist-server/service/subscription/subscription-filters.js.map +1 -1
- package/dist-server/service/work-door/index.d.ts +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/shared/task-followup.d.ts +9 -0
- package/shared/task-followup.js +25 -0
- package/tests/delegate-approval.test.ts +7 -4
- package/tests/open-doors.test.ts +1 -1
- package/translations/en.json +4 -3
- package/translations/es.json +4 -3
- package/translations/ja.json +4 -3
- package/translations/ko.json +4 -3
- package/translations/ms.json +4 -3
- package/translations/zh.json +4 -3
- package/dist-server/controllers/activity-approval/own-request.d.ts +0 -162
- package/dist-server/controllers/activity-approval/own-request.js +0 -135
- package/dist-server/controllers/activity-approval/own-request.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"own-request.js","sourceRoot":"","sources":["../../../server/controllers/activity-approval/own-request.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 상신한 사람은 자기 상신의 결재자가 될 수 없다 — **한 물음, 두 자리.**\n *\n * ── 왜 규칙이 필요한가 (ADR-0052, 2026-09-16) ─────────────────────────────\n * plant 의 「정비 완료 확인」은 상신에 `maintenance:mutation` 이 필요하고 결재선이 `MAINTENANCE-LEAD`\n * 한 단계인데, 그 권한을 보전팀장과 정비원이 **둘 다** 든다. 정비원이 끝내고 팀장이 확인하면 두 사람이지만,\n * **팀장이 직접 고치고 자기가 확인하면 한 사람**이다. 결재선을 고쳐서는 못 막는다 — 팀장을 빼면 정비가\n * 끝났는지 아는 유일한 자리가 사라진다. 그날 그 사람이 둘 다인 것이 문제라 실행 시점에 막는다.\n *\n * ── 왜 `creator` 가 아니라 `issuer` 인가 ──────────────────────────────────\n * 두 칸이 갈리는 길이 있다. `issue()` 는 `creator: user` 를 먼저 적고 `...origin` 으로 draft 를 펼치는데,\n * `origin` 이 `creator` 를 관계로 싣고 있어 **덮인다.** `issuer: user` 는 그 뒤라 안 덮인다. 그리고\n * `assertMayWorkOnDraft` 가 매니저에게 남의 draft 상신을 허용하므로, 매니저가 정비원의 draft 를 올리면\n * creator 는 정비원이고 issuer 는 매니저다.\n *\n * 그때 `creator` 로 막으면 **올리지 않은 사람을 막고, 실제로 올린 사람은 자기 상신을 결재한다** — 규칙이\n * 정확히 거꾸로 선다. 상신은 올리는 행위이고 그 판단에 책임지는 사람이 `issuer` 다. 직접 상신이면 둘이\n * 같으므로 흔한 경우는 달라지지 않는다. (2026-09-16, 아키텍트 판정)\n *\n * ── 참조는 막지 않는다 ───────────────────────────────────────────────────\n * 규칙이 막는 것은 **결재자** 자리다. 참조는 판정하지 않으므로 자기가 올린 건에 의견을 남기는 것이 이상하지\n * 않다 — 오히려 상신한 사람이 덧붙이는 말이 결재자에게 쓸모 있다.\n *\n * ── 두 자리가 같은 것을 봐야 한다 ────────────────────────────────────────\n * 누르는 자리(`checkAuthority`)와 목록에 담는 자리(`myPendingApprovalsWhere`)가 갈리면 **목록에 떴는데\n * 누르면 거절된다.** 그것이 결함이다. 한쪽은 JS 로 묻고 다른 쪽은 SQL 로 물어야 해서 코드를 그대로 나눌\n * 수는 없으므로, 두 표현을 이 파일에 나란히 두고 시험이 둘이 같은 칸을 본다는 것을 센다.\n */\n\n/** 이 사람이 이 건을 올렸나. 상신자가 없는 건(`issuer` 가 빈 옛 행)은 아무도 막지 않는다. */\nexport function raisedIt(issuerId: string | undefined | null, userId: string | undefined | null): boolean {\n return !!issuerId && !!userId && issuerId === userId\n}\n\n/** 이 자리가 판정하는 자리인가 — 빈 값은 결재다(`ApprovalLineItem.participation` 과 같은 규약). */\nexport function judges(participation: string | undefined | null): boolean {\n return participation !== 'reference'\n}\n\n/**\n * 거절하나 — **판단은 이 함수가 한다.**\n *\n * `checkAuthority` 안에 두면 시험이 못 든다. 그 파일은 엔티티를 끌어오고 엔티티는 type-graphql 을\n * 끌어와서, 시험 러너가 파일을 여는 순간 죽는다. 그래서 거기에 남겨 두면 **원문을 읽는 시험밖에** 못\n * 쓰게 되고, 원문 시험은 「그 글자가 있나」를 셀 뿐 「그래서 거절하나」를 못 센다.\n *\n * 값만 받는 함수로 빼면 네 갈래를 다 돌려 볼 수 있다 — 결재 자리 · 참조 자리 × 상신자 · 아닌 사람.\n * 부르는 쪽에 남는 것은 값을 **가져오는** 일뿐이고, 그건 원문으로 확인해도 되는 종류다.\n */\nexport function refuseToJudge({\n participation,\n issuerId,\n userId\n}: {\n participation?: string | null\n issuerId?: string | null\n userId?: string | null\n}): boolean {\n return judges(participation) && raisedIt(issuerId, userId)\n}\n\n/**\n * 같은 물음의 SQL — **`ai`(ActivityInstance)를 조인한 질의에서만** 쓴다.\n *\n * `ai.issuer != :userId` 만 쓰면 상신자가 빈 행이 SQL 의 NULL 셈법으로 조용히 빠진다 — 참이 아니라\n * 알 수 없음이 되고, 그 행들이 아무의 결재함에도 안 뜬다. 그래서 빈 것을 먼저 통과시킨다.\n *\n * 참조 자리는 이 조각이 다루지 않는다. 목록 질의는 참조를 이미 앞에서 걸러 낸다.\n */\nexport const NOT_RAISED_BY_ME_SQL = '(ai.issuer IS NULL OR ai.issuer != :userId)'\n\n/**\n * 상신한 사람이 결재하려 했다 — **커널이 쓰는 낱말과 같은 값이어야 한다.**\n *\n * `headless-twin/server/service/actuation/command-dispatcher.ts` 의 `SELF_APPROVAL` 과 짝이다.\n * **두 벌이 아니라 두 문이다** — 커널은 업무 목록을 안 지나는 길(API · AI 발의)에서 자기 커맨드를\n * 지키고, 여기는 결재 문을 지킨다. 커널↔호스트 경계를 넘어 합치지 않는다.\n *\n * 두 문이 위험한 것은 **서로 다른 답을 낼 때**다. 그래서 문장이 아니라 코드를 맞춘다 — 문장은 번역도\n * 집계도 안 되고, 고치는 날 두 문이 다른 말을 한다. 상수를 서로 import 하면 두 패키지가 묶이므로,\n * **양쪽이 각자 글자를 시험에 못 박는다.** 그래야 움직인 쪽이 빨개진다. (ADR-0052 ③)\n *\n * ⚠ 아래 `only-the-issuer-could-judge` 와 **다른 사실**이다. 이쪽은 「결재하려 한다」이고 그쪽은\n * 「설 사람이 상신자뿐이라 못 올린다」다. 글자 모양이 눈에 띄게 다른 것도 일부러다.\n */\nexport const SELF_APPROVAL = 'self-approval'\n\n/** 거절할 때 쓰는 키 — 무엇을 해야 하는지까지 문구가 말한다. */\nexport const OWN_REQUEST_REFUSAL_KEY = 'error.activity-approval cannot be judged by the person who raised it'\n\n/** 사람에게는 문장을, 붙잡는 쪽에는 `code` 를 준다 — 커널이 같은 모양으로 던진다. */\nexport function selfApprovalRefused(said: string): Error & { code: string } {\n const error = new Error(said) as Error & { code: string }\n\n error.code = SELF_APPROVAL\n return error\n}\n\n/**\n * ═══════════════════════════════════════════════════════════════════════════\n * 같은 규칙을 **상신하는 순간**에 본다 — 누르는 순간에 거절만 하면 멈춘다.\n * ═══════════════════════════════════════════════════════════════════════════\n *\n * 위의 `refuseToJudge` 는 자기 상신을 결재하려는 사람을 막는다. 그것만 세우면 **결재선에 그 사람밖에\n * 없는 건이 아무에게도 안 간다.** 정비 완료 확인이 그 모양이면 설비가 정비중으로 남고 그 라인이 선다.\n * 시드 주석이 걱정한 것이 이것이다.\n *\n * 그래서 올리는 자리에서 먼저 본다. 올릴 때 막으면 **고칠 수 있는 사람이 보는 자리**에서 걸리고,\n * 무엇을 고쳐야 하는지 그 자리에서 말할 수 있다. 결재 중에 걸리면 이미 설비가 멈춘 뒤다.\n * (2026-09-16, ADR-0052 ② · 아키텍트 판정 (다))\n *\n * ── 왜 「한 자리라도」가 아니라 「모든 자리」인가 ──────────────────────────\n * 결재선의 결재 자리는 차례로 **전부** 판정을 받아야 끝난다. 한 자리만 막혀도 그 건은 거기서 영영\n * 선다. 그래서 자리마다 본다.\n *\n * ── 아무도 못 서는 자리는 **같은 관문에서 다른 낱말로** 거절한다 ──────────\n * 그 역할을 가진 사람이 **하나도 없는** 자리도 똑같이 건을 멈춘다. 그런데 상신자 탓이 아니므로,\n * 같은 사유로 묶으면 「당신이 올려서 막혔다」는 **틀린 이유**를 대게 된다.\n *\n * 자리가 같다고 사유를 합치지 않는다 — **관리자가 할 일이 다르다.** 하나는 「그 자리에 다른 결재자를」\n * 이고 하나는 「그 역할에 사람을」이다. 낱말은 이미 있다: `approval-role-empty`(ADR-0047 ②).\n * (2026-09-16, 아키텍트 판정)\n *\n * 사람 자리가 **아무에게도 안 풀리는** 경우도 같은 자리에서 세 번째 낱말로 거절한다 — 없어진 직원을\n * 가리키는 자리다. 역할 문제가 아니므로 `approval-role-empty` 로 부르면 그것도 틀린 이유다.\n * 세 낱말이 자리를 선언하는 세 방법을 그대로 따른다:\n *\n * approval-line-missing 결재선 자체가 없다 (§`approval-expectation.ts`)\n * approval-role-empty 지목한 역할에 사람이 0명\n * approval-person-missing 지목한 사람 자리가 안 풀린다\n *\n * 전에는 `submit` 이 `error.approver is not set on the approval line` 로 잡았는데, 그때는 이미 올라간\n * 뒤다. (2026-09-16, 아키텍트 판정)\n */\n\n/** 결재 자리 하나와, 거기 설 수 있는 사람들. 역할 자리면 그 역할을 가진 사람 전부. */\nexport type JudgeableSeat = {\n /** 사람이 세는 차례 — 1차 결재, 2차 결재. 거절 문구가 이 수를 말한다. */\n order: number\n /** 역할로 건 자리인가 사람으로 건 자리인가 — **거절 사유가 갈린다.** */\n kind: 'role' | 'person'\n /** 그 자리에 설 수 있는 사람들의 id. 역할 자리면 그 역할을 가진 사람 전부. */\n couldJudge: string[]\n /** 화면에 낼 자리 이름 — 역할 이름이나 사람 이름. */\n name?: string\n /**\n * 그 자리가 **가리키던 식별자.** 안 풀리는 자리를 고치려면 「누구 자리였는지」를 알아야 한다 —\n * 이름은 못 찾으면 비는데 가리키던 값은 결재선에 그대로 남아 있다.\n */\n pointsAt?: string\n}\n\n/** 거절 사유 하나와, 그 사유로 막힌 자리들. */\nexport type SeatRefusal = {\n because: 'only-the-issuer-could-judge' | 'approval-role-empty' | 'approval-person-missing'\n seats: { order: number; name?: string; pointsAt?: string }[]\n}\n\nexport type StandingVerdict = { ok: true } | { ok: false; refusals: SeatRefusal[] }\n\n/**\n * 이 결재선을 이 사람이 올려도 되나.\n *\n * 사유가 둘이면 **둘 다 돌려준다.** 하나씩 말하면 관리자가 하나 고치고 다시 걸린다 — 자리를 전부\n * 말하는 것과 같은 이유다.\n */\nexport function judgeSomeoneElseCanJudge(input: {\n issuerId?: string | null\n /** **결재 자리만.** 참조는 판정하지 않으므로 여기 오지 않는다. */\n seats: JudgeableSeat[]\n}): StandingVerdict {\n const { issuerId, seats } = input\n\n const named = (of: JudgeableSeat[]) => of.map(({ order, name, pointsAt }) => ({ order, name, pointsAt }))\n\n /* 역할을 지목했는데 그 역할에 사람이 없다 — 상신자가 누구든 이 자리는 아무도 못 선다. */\n const roleEmpty = seats.filter(seat => seat.kind === 'role' && seat.couldJudge.length === 0)\n\n /*\n * 설 수 있는 사람이 있는데 그게 상신자뿐이다. 상신자를 모르면 이 사유는 성립하지 않는다 —\n * 「없음」을 「그 사람」으로 읽지 않는다.\n */\n const onlyIssuer = issuerId\n ? seats.filter(seat => seat.couldJudge.length > 0 && seat.couldJudge.every(one => one === issuerId))\n : []\n\n /*\n * 지목한 사람이 안 풀린다 — 없어진 직원을 가리키는 자리다. 역할 문제가 아니므로 위와 다른 낱말이다.\n * 세 낱말이 자리를 선언하는 세 방법을 그대로 따른다: line · role · person.\n */\n const personMissing = seats.filter(seat => seat.kind === 'person' && seat.couldJudge.length === 0)\n\n const refusals: SeatRefusal[] = []\n\n if (onlyIssuer.length) {\n refusals.push({ because: 'only-the-issuer-could-judge', seats: named(onlyIssuer) })\n }\n\n if (roleEmpty.length) {\n refusals.push({ because: 'approval-role-empty', seats: named(roleEmpty) })\n }\n\n if (personMissing.length) {\n refusals.push({ because: 'approval-person-missing', seats: named(personMissing) })\n }\n\n return refusals.length ? { ok: false, refusals } : { ok: true }\n}\n\nexport function standingBroken(verdict: StandingVerdict): verdict is Extract<StandingVerdict, { ok: false }> {\n return !verdict.ok\n}\n\n/** 사유마다 문구가 다르다 — 관리자가 할 일이 다르기 때문이다. */\nexport const STANDING_REFUSAL_KEYS: { [because in SeatRefusal['because']]: string } = {\n 'only-the-issuer-could-judge': 'error.approval line has nobody but the person raising it',\n 'approval-role-empty': 'error.approval line names a role that nobody holds',\n 'approval-person-missing': 'error.approval line names a person who cannot be found'\n}\n"]}
|