Public: anyone can read this; the crew can change it.

"sign in to act on your asks" lives in one module, read by bulk decide, decide and proposals #5631

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/forge:mason/5614-sign-in-to-act-on-your-asks-lives-in-one → main 1 commit fork

  • Merged. mason/5614-sign-in-to-act-on-your-asks-lives-in-one was merged into main as 98de846.

Review

Sign in to review this change.
5 files changed +37 −4
src/actions/asks_bulk.ts +2 −1
@@ -23,6 +23,7 @@ import {
2323 type FleetError,
2424 type Plan,
2525 } from "./fleet.ts";
26 import { SIGN_IN_TO_ACT } from "./asks_words.ts";
2627
2728 /**
2829 * What a bulk action on asks may be: the fleet verb each one is. Decline is
@@ -59,7 +60,7 @@ function resolve(
5960 if (!actor)
6061 return err({
6162 code: "unauthorized",
62 message: "sign in to act on your asks",
63 message: SIGN_IN_TO_ACT,
6364 });
6465 const verb =
6566 typeof action === "string" && Object.hasOwn(ASK_ACTIONS, action)
src/actions/asks_decide.ts +3 −2
@@ -15,6 +15,7 @@ import { guardedHand, letDeciderHandle, undoHandled } from "../crew/handover.ts"
1515 import { err, ok, type Result } from "../kernel/result.ts";
1616 import { askTargetsFor } from "../web/studio/asks.ts";
1717 import type { FleetError } from "./fleet.ts";
18 import { SIGN_IN_TO_ACT } from "./asks_words.ts";
1819
1920 export { HAND_COOLDOWN_MS } from "../crew/handover.ts";
2021
@@ -57,7 +58,7 @@ export async function decideAsk(
5758 item: unknown,
5859 now = Date.now(),
5960 ): Promise<Result<HandAnswer, FleetError>> {
60 if (!actor) return fail("unauthorized", "sign in to act on your asks");
61 if (!actor) return fail("unauthorized", SIGN_IN_TO_ACT);
6162 if (typeof item !== "string" || !ASK_ID.test(item))
6263 return fail("bad_action", "only a hand-over can be handed to the decider");
6364 if (app.config.decider === undefined)
@@ -86,7 +87,7 @@ export function undoDecideAsk(
8687 actor: User | undefined,
8788 decisionId: unknown,
8889 ): Result<HandAnswer, FleetError> {
89 if (!actor) return fail("unauthorized", "sign in to act on your asks");
90 if (!actor) return fail("unauthorized", SIGN_IN_TO_ACT);
9091 if (typeof decisionId !== "string" || decisionId === "")
9192 return fail("not_found", "no such decision");
9293 const undone = undoHandled(app, actor, decisionId);
src/actions/asks_words.ts added +8
@@ -0,0 +1,8 @@
1 /**
2 * What acting on asks says, said from one place (#5614): bulk decide,
3 * decide and proposals read it here, so the web, the API, MCP and the
4 * terminal word it the same.
5 */
6
7 /** Acting on an ask while signed out. */
8 export const SIGN_IN_TO_ACT = "sign in to act on your asks";
src/actions/proposals.ts +2 −1
@@ -22,6 +22,7 @@ import { NOT_A_MEMBER } from "../core/roles.ts";
2222 import { requireAbility } from "./roles.ts";
2323 import { assignIssue, addComment } from "./issues.ts";
2424 import { openPlan, parsePlan, type Planned } from "./plan.ts";
25 import { SIGN_IN_TO_ACT } from "./asks_words.ts";
2526
2627 export interface ProposalError {
2728 readonly code: "unauthorized" | "not_found" | "forbidden" | "invalid" | "conflict";
@@ -45,7 +46,7 @@ function mine(
4546 id: unknown,
4647 states: readonly ProposalState[],
4748 ): Result<{ proposal: Proposal; repo: Repo; actor: User }, ProposalError> {
48 if (!actor) return fail("unauthorized", "sign in to act on your asks");
49 if (!actor) return fail("unauthorized", SIGN_IN_TO_ACT);
4950 const proposal = typeof id === "string" ? getProposal(app.db, id) : undefined;
5051 const repo = proposal ? getRepoById(app.db, proposal.repoId) : undefined;
5152 if (!proposal || !repo || !canRead(app.db, repo, actor))
test/asks-words.test.ts added +22
@@ -0,0 +1,22 @@
1 /** "sign in to act on your asks" is typed once, in actions/asks_words.ts (#5614). */
2 import { describe, expect, test } from "bun:test";
3 import { readFileSync } from "node:fs";
4 import { join } from "node:path";
5 import { SIGN_IN_TO_ACT } from "../src/actions/asks_words.ts";
6
7 const READERS = ["asks_bulk.ts", "asks_decide.ts", "proposals.ts"];
8 const text = (file: string) => readFileSync(join(import.meta.dir, "../src/actions", file), "utf8");
9
10 describe("asks words", () => {
11 test("the sentence reads as it always has", () => {
12 expect(SIGN_IN_TO_ACT).toBe("sign in to act on your asks");
13 });
14
15 for (const file of READERS) {
16 test(`${file} imports the sentence and types no copy of it`, () => {
17 const source = text(file);
18 expect(source).not.toContain(SIGN_IN_TO_ACT);
19 expect(source).toContain('import { SIGN_IN_TO_ACT } from "./asks_words.ts";');
20 });
21 }
22 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs