@snagset/server 0.1.16 → 0.1.18
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/LICENSE +661 -0
- package/README.md +9 -10
- package/dist/app.js +51 -47
- package/dist/app.js.map +1 -1
- package/dist/bin.js +31 -32
- package/dist/bin.js.map +1 -1
- package/dist/boot.js +21 -21
- package/dist/boot.js.map +1 -1
- package/dist/config.generated.js +5 -8
- package/dist/config.generated.js.map +1 -1
- package/dist/config.js +14 -14
- package/dist/config.js.map +1 -1
- package/dist/crypto.js +1 -1
- package/dist/crypto.js.map +1 -1
- package/dist/db/connect.js +1 -1
- package/dist/db/migrate.js +11 -11
- package/dist/db/rls.js +3 -3
- package/dist/db/rls.js.map +1 -1
- package/dist/domain.js +73 -5
- package/dist/domain.js.map +1 -1
- package/dist/explain.js +1 -1
- package/dist/instance/address.js +3 -3
- package/dist/instance/address.js.map +1 -1
- package/dist/instance/settings.js +1 -1
- package/dist/integrations/github.js +3 -3
- package/dist/integrations/github.js.map +1 -1
- package/dist/integrations/inbound.js +3 -3
- package/dist/integrations/inbound.js.map +1 -1
- package/dist/integrations/linear.js +1 -1
- package/dist/integrations/linear.js.map +1 -1
- package/dist/integrations/outbox.js +4 -4
- package/dist/integrations/outbox.js.map +1 -1
- package/dist/integrations/slack.js +2 -2
- package/dist/integrations/slack.js.map +1 -1
- package/dist/jobs/index.js +3 -3
- package/dist/jobs/reaper.js +11 -11
- package/dist/jobs/reaper.js.map +1 -1
- package/dist/jobs/set.js +3 -3
- package/dist/jobs/set.js.map +1 -1
- package/dist/jobs/soon.js +3 -3
- package/dist/keys.js +3 -3
- package/dist/keys.js.map +1 -1
- package/dist/listen.js +3 -3
- package/dist/listen.js.map +1 -1
- package/dist/mail/assigned.js +10 -10
- package/dist/mail/assigned.js.map +1 -1
- package/dist/mail/digest.js +3 -3
- package/dist/mail/digest.js.map +1 -1
- package/dist/mail/index.js +2 -2
- package/dist/mail/links.js +5 -5
- package/dist/mail/mailer.js +2 -2
- package/dist/mail/notify.js +22 -22
- package/dist/mail/notify.js.map +1 -1
- package/dist/mail/resend.js +1 -1
- package/dist/mail/resolve.js +1 -1
- package/dist/mail/resolve.js.map +1 -1
- package/dist/mail/smtp.js +1 -1
- package/dist/mail/unsubscribe.js +1 -1
- package/dist/net/publicFetch.js +1 -1
- package/dist/orgs.js +5 -5
- package/dist/orgs.js.map +1 -1
- package/dist/plan.js +1 -1
- package/dist/projects.js +4 -4
- package/dist/projects.js.map +1 -1
- package/dist/routes/account.js +1 -1
- package/dist/routes/account.js.map +1 -1
- package/dist/routes/activity.js +1 -1
- package/dist/routes/anchorReports.js +9 -9
- package/dist/routes/anchorReports.js.map +1 -1
- package/dist/routes/assignees.js +4 -4
- package/dist/routes/assignees.js.map +1 -1
- package/dist/routes/attachments.js +6 -6
- package/dist/routes/attachments.js.map +1 -1
- package/dist/routes/auth.js +4 -4
- package/dist/routes/bodyLimit.js +5 -5
- package/dist/routes/bodyLimit.js.map +1 -1
- package/dist/routes/commentEdit.js +5 -5
- package/dist/routes/commentEdit.js.map +1 -1
- package/dist/routes/comments.js +24 -24
- package/dist/routes/comments.js.map +1 -1
- package/dist/routes/cors.js +33 -15
- package/dist/routes/cors.js.map +1 -1
- package/dist/routes/instance.js +3 -3
- package/dist/routes/instance.js.map +1 -1
- package/dist/routes/integrations.js +14 -11
- package/dist/routes/integrations.js.map +1 -1
- package/dist/routes/invites.js +7 -7
- package/dist/routes/invites.js.map +1 -1
- package/dist/routes/mcpAuth.js +13 -13
- package/dist/routes/mcpAuth.js.map +1 -1
- package/dist/routes/mcpToken.js +4 -4
- package/dist/routes/mcpToken.js.map +1 -1
- package/dist/routes/mcpTokens.js +27 -14
- package/dist/routes/mcpTokens.js.map +1 -1
- package/dist/routes/members.js +9 -5
- package/dist/routes/members.js.map +1 -1
- package/dist/routes/owner.js +13 -13
- package/dist/routes/owner.js.map +1 -1
- package/dist/routes/reviewLinks.js +4 -4
- package/dist/routes/reviewLinks.js.map +1 -1
- package/dist/routes/rounds.js +3 -3
- package/dist/routes/rounds.js.map +1 -1
- package/dist/routes/sessions.js +186 -71
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/sites.js +9 -9
- package/dist/routes/sites.js.map +1 -1
- package/dist/routes/threads.js +95 -95
- package/dist/routes/threads.js.map +1 -1
- package/dist/routes/widget.js +5 -5
- package/dist/routes/widget.js.map +1 -1
- package/dist/serverless.js +4 -4
- package/dist/serverless.js.map +1 -1
- package/dist/session.js +8 -8
- package/dist/session.js.map +1 -1
- package/dist/storage/bucket.js +4 -4
- package/dist/storage/bucket.js.map +1 -1
- package/dist/storage/settings.js +4 -4
- package/dist/storage/settings.js.map +1 -1
- package/dist/studioReviewers.js +4 -4
- package/dist/vendor/adapters/outbound/fence.js +2 -2
- package/dist/vendor/adapters/outbound/sanitise.js +14 -14
- package/dist/vendor/mcp/bin.js +4 -4
- package/dist/vendor/mcp/client.js +3 -3
- package/dist/vendor/mcp/server.js +3 -3
- package/dist/vendor/mcp/source.js +13 -13
- package/dist/vendor/mcp/view.js +15 -15
- package/dist/vendor/types/brief.js +2 -2
- package/dist/vendor/types/index.js +1 -1
- package/dist/vendor/types/names.js +20 -18
- package/dist/vendor/widget/object.js +3 -3
- package/dist/vendor/widget/predicates.js +38 -39
- package/package.json +1 -5
- package/static/dashboard/assets/{CompositeItem-DP7FLsIz.js → CompositeItem-D1SCvKo_.js} +1 -1
- package/static/dashboard/assets/{ConfirmDialog-B-mNmk6U.js → ConfirmDialog-DdUOWt96.js} +1 -1
- package/static/dashboard/assets/{CopyButton-bsaLPvqU.js → CopyButton-DX7vax3M.js} +1 -1
- package/static/dashboard/assets/{FieldItemContext-Cz9anwiZ.js → FieldItemContext-CMpCHNX8.js} +1 -1
- package/static/dashboard/assets/{InstallTag-DDMHFPFi.js → InstallTag-DkYPsEI0.js} +1 -1
- package/static/dashboard/assets/{SaveState-rgq6rRHH.js → SaveState-D0Hl8cny.js} +1 -1
- package/static/dashboard/assets/{_app-C5aeP_jI.js → _app-CcUZ9WT2.js} +1 -1
- package/static/dashboard/assets/{_app-B--Q2p1D.js → _app-CnG-wKIX.js} +1 -1
- package/static/dashboard/assets/{activity-CmpMwfWp.js → activity-DnvsedIb.js} +1 -1
- package/static/dashboard/assets/{arrow-left-BN3lUG8m.js → arrow-left-4jbTF1bA.js} +1 -1
- package/static/dashboard/assets/{avatar-4OkpxHzf.js → avatar-BKSc7tnv.js} +1 -1
- package/static/dashboard/assets/{badge-BGUQxxes.js → badge-aWVtPffe.js} +1 -1
- package/static/dashboard/assets/{card-BX32udhB.js → card-Bz0VdsxC.js} +1 -1
- package/static/dashboard/assets/{check-DjkY9Lhe.js → check-Ti2IOlgc.js} +1 -1
- package/static/dashboard/assets/{chevron-right-w26JMtvi.js → chevron-right-g-zbIopD.js} +1 -1
- package/static/dashboard/assets/{copy-BtOpNPn3.js → copy-BwBuD0FO.js} +1 -1
- package/static/dashboard/assets/{dialog-Ca351GqX.js → dialog-DdpHZobU.js} +1 -1
- package/static/dashboard/assets/{dropdown-menu-BdM8D0_i.js → dropdown-menu-CB2L3nig.js} +1 -1
- package/static/dashboard/assets/{image-off-DBc5pfc8.js → image-off-w_ej9pIJ.js} +1 -1
- package/static/dashboard/assets/{index-Bvmz5Xph.js → index-DtF8YHqn.js} +3 -3
- package/static/dashboard/assets/{invite-b1vVPR4n.js → invite-Dy3iQjzf.js} +1 -1
- package/static/dashboard/assets/{label-CeHVAC98.js → label-Dj8L94iS.js} +1 -1
- package/static/dashboard/assets/{layout-grid-BJUJgcuD.js → layout-grid-DuweH0Vl.js} +1 -1
- package/static/dashboard/assets/me-7-r9OeMR.js +1 -0
- package/static/dashboard/assets/{parts-BU_5BLga.js → parts-CA4cbfy3.js} +1 -1
- package/static/dashboard/assets/{plus-DW3meZh8.js → plus-CEWgXDLj.js} +1 -1
- package/static/dashboard/assets/s._site-D69M50OI.js +1 -0
- package/static/dashboard/assets/{s._site.comments-CyIqVrl3.js → s._site.comments-DNJ2SE5c.js} +1 -1
- package/static/dashboard/assets/{s._site.reviewers-muaVzTtT.js → s._site.reviewers-B07NzSWj.js} +1 -1
- package/static/dashboard/assets/{s._site.settings-Bow6VdXW.js → s._site.settings-B577G5iG.js} +1 -1
- package/static/dashboard/assets/{setup-B5fdtoM-.js → setup-DcjjtB3g.js} +1 -1
- package/static/dashboard/assets/{sign-in-D9Bhw619.js → sign-in-gfvOs6Jw.js} +1 -1
- package/static/dashboard/assets/{sign-up-CK-LWLzn.js → sign-up-CFJt7ibH.js} +1 -1
- package/static/dashboard/assets/{sites-CLB6RzU6.js → sites-DbB5cjz5.js} +1 -1
- package/static/dashboard/assets/studio-BO-MHFqc.js +1 -0
- package/static/dashboard/assets/{studio-CVFUbJQb.js → studio-D9GxJaSF.js} +1 -1
- package/static/dashboard/assets/{studio.index-CUtMjh5_.js → studio.index-DktAxIPT.js} +1 -1
- package/static/dashboard/assets/studio.integrations-CbLyqPLX.js +1 -0
- package/static/dashboard/assets/{studio.members-BcVrAT7r.js → studio.members-DFtIL3JS.js} +1 -1
- package/static/dashboard/assets/{sun-BzCBfLxA.js → sun-Bg7U-6Y0.js} +1 -1
- package/static/dashboard/assets/{switch-Djsy8JA6.js → switch-CTN6hIca.js} +1 -1
- package/static/dashboard/assets/{table-Cnpowiv-.js → table-zQ3pj50_.js} +1 -1
- package/static/dashboard/assets/{useAriaLabelledBy-D35XdVIh.js → useAriaLabelledBy-BsNncGbx.js} +1 -1
- package/static/dashboard/assets/{useBaseQuery-DztMyAqa.js → useBaseQuery-DSqwWD_O.js} +1 -1
- package/static/dashboard/assets/useQuery-OgrKuHbc.js +1 -0
- package/static/dashboard/assets/useRender-DOFVvGfR.js +1 -0
- package/static/dashboard/assets/{useValueChanged-DY7n1sYE.js → useValueChanged-B9k7l-mp.js} +1 -1
- package/static/dashboard/assets/{users-CR2o4PsB.js → users-CRiOyD0f.js} +1 -1
- package/static/dashboard/assets/{welcome-DJ_8xHTE.js → welcome-DT2DB4jN.js} +1 -1
- package/static/dashboard/assets/{widget-signin-BOulktuR.js → widget-signin-CC9owVvs.js} +1 -1
- package/static/dashboard/assets/{you-DJGezimL.js → you-CtcXklc_.js} +1 -1
- package/static/dashboard/assets/{zod-4RphBaVj.js → zod-CLxHj89d.js} +1 -1
- package/static/dashboard/index.html +1 -1
- package/static/widget/snag.capture.js +1 -1
- package/static/widget/snag.runtime.js +2 -2
- package/static/dashboard/assets/me-zNn3-t75.js +0 -1
- package/static/dashboard/assets/s._site-DP3hLlXp.js +0 -1
- package/static/dashboard/assets/studio-CuiXjnSt.js +0 -1
- package/static/dashboard/assets/studio.integrations-CiQ83f7Q.js +0 -1
- package/static/dashboard/assets/useQuery-DCEPkmeo.js +0 -1
- package/static/dashboard/assets/useRender-C2NyqaXd.js +0 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { RESERVED_URL_PARAMS } from "../types/names.js";
|
|
2
2
|
/**
|
|
3
|
-
* The redaction module
|
|
3
|
+
* The redaction module.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* "Redaction is not optional and cannot be disabled — only *extended*.
|
|
6
6
|
* There is no `redact: false`." v0 ships `redactText`, `redactUrl`, every shape
|
|
7
|
-
* rule
|
|
8
|
-
* first two and
|
|
7
|
+
* rule .3 and `isSensitiveValue` — because `CaptureContext.url` needs the
|
|
8
|
+
* first two and the selector generation needs the third. `redactObject` and the
|
|
9
9
|
* record-time pipeline arrive with breadcrumbs in v0.1.
|
|
10
10
|
*
|
|
11
11
|
* ── Why this file lives in the RUNTIME chunk ──
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
* tags that artefact v0.1 so it does not exist,
|
|
15
|
-
* fetching any capture chunk, and
|
|
13
|
+
* The design says the module lives in `snag.capture.js`. It cannot at v0:
|
|
14
|
+
* tags that artefact v0.1 so it does not exist, forbids activation
|
|
15
|
+
* fetching any capture chunk, and the `createElementAnchor` calls
|
|
16
16
|
* `isSensitiveValue` SYNCHRONOUSLY at pin time so it cannot await an import.
|
|
17
|
-
*
|
|
17
|
+
* Rules on it: "One copy, in snag.runtime.js; snag.capture.js
|
|
18
18
|
* imports from it." The spec edit that records the inversion is still owed.
|
|
19
19
|
*
|
|
20
20
|
* ── The one thing to know before editing ──
|
|
@@ -26,17 +26,17 @@ import { RESERVED_URL_PARAMS } from "../types/names.js";
|
|
|
26
26
|
* input. `hits()` exists for exactly that reason.
|
|
27
27
|
*/
|
|
28
28
|
/**
|
|
29
|
-
* The key vocabulary, byte-for-byte
|
|
29
|
+
* The key vocabulary, byte-for-byte.
|
|
30
30
|
*
|
|
31
|
-
*
|
|
32
|
-
* absent —
|
|
31
|
+
* "if the two ever differ, 00 wins." `pin` and `sig` are DELIBERATELY
|
|
32
|
+
* absent — the design gives the reason, and adding them is not a fix.
|
|
33
33
|
*/
|
|
34
34
|
const KEY = `pass(?:word|wd)?|pwd|secret|token|api[_-]?key|apikey|auth(?:orization)?|` +
|
|
35
35
|
`credential|session|sid|cookie|jwt|bearer|otp|mfa|totp|cvv|cvc|ssn|nino|iban|` +
|
|
36
36
|
`card(?:[_-]?number)?|account[_-]?number|private[_-]?key|signature|` +
|
|
37
37
|
`client[_-]?secret|refresh[_-]?token|access[_-]?token`;
|
|
38
38
|
/**
|
|
39
|
-
* key = value, in any of the shapes real payloads use
|
|
39
|
+
* key = value, in any of the shapes real payloads use., verbatim.
|
|
40
40
|
*
|
|
41
41
|
* THE LEADING BOUNDARY IS A LOOKBEHIND, NOT `\b`. `_` is a word character, so
|
|
42
42
|
* `\b` finds no boundary between the `B` and the `P` of `DB_PASSWORD` and the
|
|
@@ -53,7 +53,7 @@ const KEY = `pass(?:word|wd)?|pwd|secret|token|api[_-]?key|apikey|auth(?:orizati
|
|
|
53
53
|
* Group 1 is the optional quote BEFORE the key; group 2 is the value's opening
|
|
54
54
|
* quote; group 3 the quoted value body; group 4 the unquoted value. The only
|
|
55
55
|
* backreference in the whole rule set is this one's `\2`, which is deliberate:
|
|
56
|
-
*
|
|
56
|
+
* The design makes catastrophic backtracking a hard review criterion, because it
|
|
57
57
|
* is a denial of service on the reviewer's own main thread.
|
|
58
58
|
*/
|
|
59
59
|
const KV = new RegExp(`(["'\`]?)(?<![A-Za-z0-9])(?:${KEY})[\\w-]*\\b\\1?\\s*[:=]\\s*` +
|
|
@@ -74,7 +74,7 @@ const SCHEME_WORD = /^(?:Bearer|Basic|Digest|Negotiate|Token)$/i;
|
|
|
74
74
|
* emitted `Authorization: [redacted] abcdefgh12345`. The word was redacted and
|
|
75
75
|
* THE TOKEN WAS PUBLISHED. AUTH_SCHEME could no longer help, because the scheme
|
|
76
76
|
* it keys on had just been replaced. Found by running the rules rather than
|
|
77
|
-
* reading them, which is what
|
|
77
|
+
* reading them, which is what the own preamble asks for.
|
|
78
78
|
*
|
|
79
79
|
* So AUTH_SCHEME runs first (see redactText), and KV then leaves a scheme word
|
|
80
80
|
* alone *only when the credential after it is already gone*. Both halves are
|
|
@@ -100,7 +100,7 @@ const kvReplace = (m, _q0, q, qv, uv, offset, whole) => {
|
|
|
100
100
|
const head = m.slice(0, m.length - val.length);
|
|
101
101
|
return head + (q ? `${q}[redacted]${q}` : "[redacted]");
|
|
102
102
|
};
|
|
103
|
-
// The shape rules
|
|
103
|
+
// The shape rules, verbatim.
|
|
104
104
|
const DATA_URL = /data:[a-z0-9.+-]*\/?[a-z0-9.+-]*;base64,[A-Za-z0-9+/=]{16,}/gi;
|
|
105
105
|
const JWT = /\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{0,}/g;
|
|
106
106
|
const KEY_PREFIX = /\b(sk-[A-Za-z0-9]+-[A-Za-z0-9_-]{20,}|sk-ant-[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9]{20,}|(sk|pk|rk)_(live|test)_[A-Za-z0-9]{16,}|gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{16,}|xox[baprs]-[A-Za-z0-9-]{10,}|xapp-[A-Za-z0-9-]{10,}|AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|ya29\.[A-Za-z0-9_-]{20,}|SG\.[A-Za-z0-9_-]{20,}|npm_[A-Za-z0-9]{30,}|dop_v1_[a-f0-9]{40,}|shpat_[a-f0-9]{30,}|sbp_[a-f0-9]{30,}|hf_[A-Za-z0-9]{30,}|nvapi-[A-Za-z0-9_-]{20,})\b/g;
|
|
@@ -110,14 +110,14 @@ const CARD_CAND = /\b(?:\d[ -]?){12,18}\d\b/g;
|
|
|
110
110
|
const B64 = /\b(?=[A-Za-z0-9+/]*[a-z])(?=[A-Za-z0-9+/]*[A-Z])(?=[A-Za-z0-9+/]*\d)[A-Za-z0-9+/]{40,}={0,2}\b/g;
|
|
111
111
|
const HEX = /\b[0-9a-f]{32,}\b/gi;
|
|
112
112
|
/**
|
|
113
|
-
* EXTENSIONS
|
|
113
|
+
* EXTENSIONS.: redaction "cannot be disabled — only *extended*", which
|
|
114
114
|
* makes adding a rule the sanctioned move and rewriting a spec-verbatim one the
|
|
115
|
-
* unsanctioned one. Every constant above is copied from
|
|
115
|
+
* unsanctioned one. Every constant above is copied from / and
|
|
116
116
|
* stays untouched; each rule below closes a hole an adversarial pass found by
|
|
117
117
|
* running the module, with the shape that got through named in its comment.
|
|
118
118
|
*/
|
|
119
119
|
/**
|
|
120
|
-
* Base64URL. B64's class is `[A-Za-z0-9+/]`, verbatim
|
|
120
|
+
* Base64URL. B64's class is `[A-Za-z0-9+/]`, verbatim — so a single
|
|
121
121
|
* `_` or `-` chops a token into runs under the 40-char floor and B64 never
|
|
122
122
|
* fires at all. A Cloudflare API token is exactly 40 characters of
|
|
123
123
|
* `[A-Za-z0-9_-]` with no vendor prefix for KEY_PREFIX to key on, and walked
|
|
@@ -149,7 +149,7 @@ const URL_CRED = /\b[a-z][a-z0-9+.-]*:\/\/[^\s/:@]+:[^\s/@]+@/gi;
|
|
|
149
149
|
* it (used by `isSensitiveValue` only).
|
|
150
150
|
*
|
|
151
151
|
* ANCHORED, deliberately: it must fire on a value that is a credential and
|
|
152
|
-
* never on prose that merely contains one, or
|
|
152
|
+
* never on prose that merely contains one, or the negative corpus
|
|
153
153
|
* `/orders/2024`, `4 items`, `cardNumber` — starts failing and 03 loses
|
|
154
154
|
* selectors it should have kept. Mixed case AND a digit AND 24+ characters is
|
|
155
155
|
* what separates an Azure client secret from `product-card-item-12345678`.
|
|
@@ -170,7 +170,7 @@ function hits(re, s) {
|
|
|
170
170
|
return found;
|
|
171
171
|
}
|
|
172
172
|
/**
|
|
173
|
-
* The Luhn checksum
|
|
173
|
+
* The Luhn checksum.: "The Luhn gate is not optional and not forkable."
|
|
174
174
|
*
|
|
175
175
|
* Three mechanics the spec asserts without specifying, decided here and written
|
|
176
176
|
* down rather than left as folklore:
|
|
@@ -209,23 +209,23 @@ function cardHit(s) {
|
|
|
209
209
|
return false;
|
|
210
210
|
}
|
|
211
211
|
/**
|
|
212
|
-
* Free text — messages, serialised data, accessible names
|
|
212
|
+
* Free text — messages, serialised data, accessible names.
|
|
213
213
|
*
|
|
214
|
-
* ORDER IS NORMATIVE and the reason is stated
|
|
214
|
+
* ORDER IS NORMATIVE and the reason is stated: "broader patterns run
|
|
215
215
|
* later so they cannot swallow the input a narrower pattern would have labelled
|
|
216
216
|
* precisely." A JWT is base64-ish and hex-ish; if B64 ran first every token
|
|
217
217
|
* would come out as `[redacted:b64:210]` and the reviewer would lose the one
|
|
218
218
|
* word that told them what leaked. KV runs at position 2, before every shape
|
|
219
219
|
* rule, and both always run.
|
|
220
220
|
*
|
|
221
|
-
* No caps are applied here.
|
|
221
|
+
* No caps are applied here. The pre/post caps are PER FIELD and this
|
|
222
222
|
* signature carries no field identity — the caller applies them, which at v0
|
|
223
223
|
* means exactly one call site (`CaptureContext.url`).
|
|
224
224
|
*/
|
|
225
225
|
export function redactText(s) {
|
|
226
226
|
let out = s;
|
|
227
227
|
out = out.replace(DATA_URL, "data:[redacted]"); // 1
|
|
228
|
-
// AUTH_SCHEME is MOVED AHEAD OF KV —
|
|
228
|
+
// AUTH_SCHEME is MOVED AHEAD OF KV — numbers it 5. The letter of the
|
|
229
229
|
// table leaks (see kvReplace); its stated principle — "broader patterns run
|
|
230
230
|
// later so they cannot swallow the input a narrower pattern would have
|
|
231
231
|
// labelled precisely" — is exactly why it has to move, because KV is the
|
|
@@ -253,15 +253,14 @@ export function redactText(s) {
|
|
|
253
253
|
}
|
|
254
254
|
/** Our own registered query parameters. Values are KEPT — see redactUrl. */
|
|
255
255
|
const OURS = RESERVED_URL_PARAMS.query;
|
|
256
|
-
/** The review-link secret
|
|
256
|
+
/** The review-link secret. It lives in the FRAGMENT and is redacted
|
|
257
257
|
* wherever it appears — the one parameter whose value is never displayable. */
|
|
258
258
|
const SECRET_PARAMS = RESERVED_URL_PARAMS.fragment;
|
|
259
259
|
/**
|
|
260
260
|
* A URL: a structured pass first, then `redactText` over the serialisation
|
|
261
|
-
* (04 §4.4).
|
|
262
261
|
*
|
|
263
262
|
* ALLOW-LIST, NOT DENY-LIST. Parameter *names* survive because the name alone is
|
|
264
|
-
* diagnostic; values do not. The default is empty and stays empty —
|
|
263
|
+
* diagnostic; values do not. The default is empty and stays empty — the design is
|
|
265
264
|
* explicit that "the failure mode of a too-loose default (leaking a magic-link
|
|
266
265
|
* token in every captured URL) is catastrophic". A starter list worth
|
|
267
266
|
* documenting, never defaulting: page, tab, view, sort, filter, locale, lang.
|
|
@@ -270,7 +269,7 @@ const SECRET_PARAMS = RESERVED_URL_PARAMS.fragment;
|
|
|
270
269
|
* permalink is unreadable without the permalink — except `snag_k`, which is the
|
|
271
270
|
* review-link secret and is always redacted.
|
|
272
271
|
*
|
|
273
|
-
* URL PATHS ARE NOT FULLY REDACTED
|
|
272
|
+
* URL PATHS ARE NOT FULLY REDACTED. Path segments get no
|
|
274
273
|
* structural treatment; they are covered only by the trailing `redactText`.
|
|
275
274
|
* That is deliberate and documented, not an oversight.
|
|
276
275
|
*/
|
|
@@ -279,7 +278,7 @@ export function redactUrl(raw, allow = []) {
|
|
|
279
278
|
try {
|
|
280
279
|
// `globalThis.location`, reached through a cast, rather than the bare
|
|
281
280
|
// `location` global. The runtime guard was always right; the TYPE was
|
|
282
|
-
// browser-only, and
|
|
281
|
+
// browser-only, and the design requires this module to be usable
|
|
283
282
|
// server-side ("publish that module as an isomorphic export usable
|
|
284
283
|
// server-side, not only inside widget-core"). Under Node's lib the bare
|
|
285
284
|
// global does not exist to name, so the file did not compile there at all.
|
|
@@ -288,13 +287,13 @@ export function redactUrl(raw, allow = []) {
|
|
|
288
287
|
}
|
|
289
288
|
catch {
|
|
290
289
|
// Not parseable as a URL — it still goes through the text rules rather than
|
|
291
|
-
// through untouched
|
|
290
|
+
// through untouched.: nothing reaches a surface un-redacted.
|
|
292
291
|
return redactText(raw);
|
|
293
292
|
}
|
|
294
293
|
u.username = "";
|
|
295
294
|
u.password = "";
|
|
296
295
|
for (const k of [...u.searchParams.keys()]) {
|
|
297
|
-
// From the registry, not typed: `snag_k` is a registered name
|
|
296
|
+
// From the registry, not typed: `snag_k` is a registered name and
|
|
298
297
|
// a rename would have left this literal behind — so the ONE parameter that
|
|
299
298
|
// must always be redacted would quietly stop being.
|
|
300
299
|
if (SECRET_PARAMS.includes(k)) {
|
|
@@ -323,34 +322,34 @@ export function redactUrl(raw, allow = []) {
|
|
|
323
322
|
if (u.hash && u.hash.length > 1)
|
|
324
323
|
u.hash = allow.includes("#") ? u.hash : "#[redacted]";
|
|
325
324
|
// `URLSearchParams` serialises form-urlencoded, which escapes [ and ] — so
|
|
326
|
-
// `set(k, "[redacted]")` comes back out as `token=%5Bredacted%5D` and
|
|
325
|
+
// `set(k, "[redacted]")` comes back out as `token=%5Bredacted%5D` and the own
|
|
327
326
|
// illustration (`?utm_source=[redacted]&token=[redacted]`) is unreachable.
|
|
328
327
|
// Un-escaping just our own marker is narrower than hand-building the query
|
|
329
328
|
// string and does not touch any value the host page owns.
|
|
330
329
|
return redactText(u.toString().replace(/%5Bredacted%5D/gi, "[redacted]"));
|
|
331
330
|
}
|
|
332
331
|
/**
|
|
333
|
-
* Should this attribute value stay out of a generated selector?
|
|
332
|
+
* Should this attribute value stay out of a generated selector?
|
|
334
333
|
*
|
|
335
334
|
* THE SINGLE NORMATIVE DEFINITION — 03 imports this symbol rather than carrying
|
|
336
|
-
* its own copy, and AC C1c greps for a second one. The 120-char clause is
|
|
337
|
-
* value;
|
|
335
|
+
* its own copy, and AC C1c greps for a second one. The 120-char clause is the
|
|
336
|
+
* value; the 100 is deleted. The hex threshold is 32; the 24 is deleted.
|
|
338
337
|
*
|
|
339
338
|
* Composed from exactly seven shapes plus the length clause — deliberately NOT
|
|
340
339
|
* from KV, AUTH_SCHEME or UUID, which describe text that contains a secret
|
|
341
340
|
* rather than a value that IS one.
|
|
342
341
|
*
|
|
343
|
-
*
|
|
342
|
+
* The design is careful about what this does not do: "This does not make selectors
|
|
344
343
|
* private" — `a[href="/users/jane.doe/invoices"]` still passes the guard. It
|
|
345
344
|
* keeps credentials out of selectors, not personal data.
|
|
346
345
|
*/
|
|
347
346
|
/**
|
|
348
|
-
* The key test for OBJECT keys —
|
|
347
|
+
* The key test for OBJECT keys — the "key-first" step for
|
|
349
348
|
* `Breadcrumb.data` and (v1) `custom`. Same vocabulary, same boundary
|
|
350
349
|
* semantics as KV: the lookbehind is what lets `DB_PASSWORD` and the
|
|
351
350
|
* `[\w-]*` tail is what lets `refreshToken`/`token_count` match, exactly as
|
|
352
351
|
* the string form `db_password=…` would. One list, two syntaxes — a separate
|
|
353
|
-
* key list here is the fork
|
|
352
|
+
* key list here is the fork the design forbids.
|
|
354
353
|
*/
|
|
355
354
|
const KEY_NAME = new RegExp(`(?<![A-Za-z0-9])(?:${KEY})[\\w-]*$`, "i");
|
|
356
355
|
export function isSensitiveKey(k) {
|
|
@@ -366,7 +365,7 @@ export function isSensitiveValue(v) {
|
|
|
366
365
|
hits(B64, v) ||
|
|
367
366
|
hits(DATA_URL, v) ||
|
|
368
367
|
// The extensions. This predicate is the ENTIRE defence for AnchorRecord
|
|
369
|
-
// .label —
|
|
368
|
+
// .label — the design gives that field redaction "none" precisely because this
|
|
370
369
|
// gate stands in front of it — so a shape that gets past here goes verbatim
|
|
371
370
|
// into storage, the dock, the Markdown export and any issue built from it.
|
|
372
371
|
hits(B64URL, v) ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snagset/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The Snagset server: API, dashboard and widget in one package. Node and Postgres, or Vercel.",
|
|
@@ -19,10 +19,6 @@
|
|
|
19
19
|
"migrate": "node --experimental-strip-types src/db/migrate.ts",
|
|
20
20
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
21
|
"test": "node --experimental-strip-types --test --test-concurrency=1 test/*.test.ts",
|
|
22
|
-
"gen:config": "node scripts/gen-config.mjs",
|
|
23
|
-
"gen:config:check": "node scripts/gen-config.mjs --check",
|
|
24
|
-
"gen:migration": "node scripts/gen-migration.mjs",
|
|
25
|
-
"gen:migration:check": "node scripts/gen-migration.mjs --check",
|
|
26
22
|
"build": "node scripts/build.mjs",
|
|
27
23
|
"prepack": "node scripts/build.mjs && node ../../tools/publish-manifest.mjs strip",
|
|
28
24
|
"postpack": "node ../../tools/publish-manifest.mjs restore"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as l,d as O,e as M,a3 as w,j as T,aE as _,a6 as j,E as k,aD as D,i as H}from"./index-
|
|
1
|
+
import{r as l,d as O,e as M,a3 as w,j as T,aE as _,a6 as j,E as k,aD as D,i as H}from"./index-DtF8YHqn.js";const Y=l.createContext(void 0);function K(){return l.useContext(Y)?.direction??"ltr"}const S=l.createContext({register:()=>{},unregister:()=>{},subscribeMapChange:()=>()=>{},nextIndexRef:{current:0}});function B(){return l.useContext(S)}function F(s={}){const{guess:o,label:e,metadata:r,textRef:f,index:t}=s,{register:i,unregister:u,subscribeMapChange:d,nextIndexRef:h}=B(),c=l.useRef(-1),[g,C]=l.useState(t==null&&o?()=>{if(c.current===-1){const x=h.current;h.current+=1,c.current=x}return c.current}:-1),v=t??g,R=l.useRef(null),E=l.useCallback(x=>{const b=R.current;b&&u(b),R.current=x,x&&i(x,{metadata:r??null,index:t??null,label:e,textRef:f})},[t,i,u,r,e,f]);return O(()=>{if(t==null)return d(x=>{const b=R.current?x.get(R.current)?.index:null;b!=null&&C(b)})},[t,d]),{ref:E,index:v}}function Q(s){const{children:o,elementsRef:e,labelsRef:r,onMapChange:f}=s,t=M(f),[,i]=l.useState(!1),u=w(W).current,d=w(U).current,h=l.useRef(0),c=l.useRef(!0),g=l.useRef([]),C=l.useRef(null),v=M(()=>{c.current||(c.current=!0,i(n=>!n))}),R=M((n,p)=>{d.set(n,p),v()}),E=M(n=>{d.delete(n),v()}),x=M(n=>{const p=new Map;return e.current.length=0,r&&(r.current.length=0),n.forEach(a=>{p.set(a.element,{...a.registration.metadata??{},index:a.index}),e.current[a.index]=a.element,r&&(r.current[a.index]=a.registration.label!==void 0?a.registration.label:a.registration.textRef?.current?.textContent??a.element.textContent)}),h.current=e.current.length,p});function b(n){if(C.current?.disconnect(),C.current=null,typeof MutationObserver!="function"||n.length<2)return;const p=new MutationObserver(m=>{if(!J(m))return;let I=null;for(const L of n)if(L.isConnected){if(I&&y(I,L)>0){p.disconnect(),v();return}I=L}});C.current=p;const a=new Set;for(let m=1;m<n.length;m+=1){const I=G(n[m-1],n[m]);I&&a.add(I)}a.forEach(m=>p.observe(m,{childList:!0}))}const N=M(()=>{const[n,p]=z(d),a=x(n);b(p),g.current=n,c.current=!1,u.forEach(m=>m(a)),t(a)});O(()=>(c.current||x(g.current),()=>{e.current=[],r&&(r.current=[])}),[e,r,x]),O(()=>{c.current&&N()}),O(()=>()=>{C.current?.disconnect(),c.current=!0},[]);const P=M(n=>(u.add(n),()=>{u.delete(n)})),A=l.useMemo(()=>({register:R,unregister:E,subscribeMapChange:P,nextIndexRef:h}),[R,E,P,h]);return T.jsx(S.Provider,{value:A,children:o})}function U(){return new Map}function W(){return new Set}function z(s){const o=new Set,e=[],r=[];s.forEach((t,i)=>{if(!i.isConnected)return;const u=t.index,d={index:u??-1,element:i,registration:t};u===null?r.push(d):u>=0&&(o.add(u),e.push(d))});let f=0;return r.sort((t,i)=>y(t.element,i.element)),r.forEach(t=>{for(;o.has(f);)f+=1;t.index=f,e.push(t),f+=1}),o.size>0&&e.sort((t,i)=>t.index-i.index),[e,r.map(t=>t.element)]}function G(s,o){let e=s.parentElement;for(;e&&!e.contains(o);)e=e.parentElement;return e}function J(s){for(const o of s)for(let e=0;e<o.removedNodes.length;e+=1)if(o.removedNodes[e].isConnected)return!0;return!1}function y(s,o){return s.compareDocumentPosition(o)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1}function V(s={}){const{highlightItemOnHover:o,highlightedIndex:e,onHighlightedIndexChange:r}=_(),{ref:f,index:t}=F(s),i=e===t,u=l.useRef(null),d=j(f,u);return{compositeProps:{tabIndex:i?0:-1,onFocus(){r(t)},onMouseMove(){const c=u.current;if(!o||!c)return;const g=c.hasAttribute("disabled")||c.ariaDisabled==="true";!i&&!g&&c.focus()}},compositeRef:d,index:t}}function X(s){const{render:o,className:e,style:r,state:f=k,props:t=D,refs:i=D,metadata:u,stateAttributesMapping:d,tag:h="div",...c}=s,{compositeProps:g,compositeRef:C}=V({metadata:u});return H(h,s,{state:f,ref:[C,...i],props:[g,...t,c],stateAttributesMapping:d})}export{Q as C,F as a,X as b,K as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as i,j as e,B as x}from"./index-
|
|
1
|
+
import{r as i,j as e,B as x}from"./index-DtF8YHqn.js";import{E as u,G as g,I as C,H as D,J as v,K as b}from"./dialog-DdpHZobU.js";import{L as E,I}from"./label-Dj8L94iS.js";function T({open:t,onOpenChange:o,title:m,description:r,children:h,confirmLabel:j,confirmWord:l,busy:s=!1,onConfirm:p}){const[n,c]=i.useState(""),d=i.useId();i.useEffect(()=>{t&&c("")},[t]);const f=!l||n.trim()===l;return e.jsx(u,{open:t,onOpenChange:a=>{!a&&s||o(a)},children:e.jsx(g,{showCloseButton:!1,children:e.jsxs("form",{className:"flex flex-col gap-4",onSubmit:a=>{a.preventDefault(),f&&!s&&p()},children:[e.jsxs(C,{children:[e.jsx(D,{children:m}),r&&e.jsx(v,{children:r})]}),h,l&&e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsxs(E,{htmlFor:d,children:["Type ",e.jsx("b",{className:"font-semibold text-foreground",children:l})," to confirm"]}),e.jsx(I,{id:d,value:n,autoComplete:"off",spellCheck:!1,disabled:s,onChange:a=>c(a.target.value)})]}),e.jsxs(b,{children:[e.jsx(x,{type:"button",variant:"outline",disabled:s,onClick:()=>o(!1),children:"Cancel"}),e.jsx(x,{type:"submit",variant:"destructive",loading:s,disabled:!f,children:s?"Working…":j})]})]})})})}export{T as C};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as n,j as t,B as c}from"./index-
|
|
1
|
+
import{r as n,j as t,B as c}from"./index-DtF8YHqn.js";import{C}from"./check-Ti2IOlgc.js";import{C as m}from"./copy-BwBuD0FO.js";function l({text:r,label:e="Copy",withText:s=!1,size:a="icon-sm",className:p}){const[o,i]=n.useState(!1);return t.jsxs(c,{type:"button",variant:"outline",size:s?"sm":a,className:p,"aria-label":o?"Copied":e,onClick:()=>{navigator.clipboard?.writeText(r).catch(()=>{}),i(!0),setTimeout(()=>i(!1),1500)},children:[o?t.jsx(C,{}):t.jsx(m,{}),s&&(o?"Copied":e)]})}export{l as C};
|
package/static/dashboard/assets/{FieldItemContext-Cz9anwiZ.js → FieldItemContext-CMpCHNX8.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as t}from"./index-
|
|
1
|
+
import{r as t}from"./index-DtF8YHqn.js";const e=t.createContext({disabled:!1});function r(){return t.useContext(e)}export{r as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as o,j as e,B as i,aO as n}from"./index-
|
|
1
|
+
import{r as o,j as e,B as i,aO as n}from"./index-DtF8YHqn.js";import{C as c}from"./check-Ti2IOlgc.js";import{C as l}from"./copy-BwBuD0FO.js";function p(t){return`<script src="${location.origin}/snag.js" ${n("site")}="${t}" defer><\/script>`}function g({uid:t}){const[r,a]=o.useState(!1),s=p(t);return e.jsxs("div",{className:"relative rounded-md border border-border bg-background px-3 py-2.5 pr-11 font-mono text-[12.5px] leading-relaxed",children:[e.jsx("code",{className:"whitespace-pre-wrap break-all",children:s}),e.jsx(i,{variant:"ghost",size:"icon-sm",className:"absolute right-1.5 top-1.5","aria-label":r?"Copied":"Copy the tag",onClick:()=>{navigator.clipboard?.writeText(s),a(!0),setTimeout(()=>a(!1),1500)},children:r?e.jsx(c,{}):e.jsx(l,{})})]})}export{g as I};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r,j as e,aN as o}from"./index-
|
|
1
|
+
import{r,j as e,aN as o}from"./index-DtF8YHqn.js";function l({saving:s,savedAt:t}){const[i,a]=r.useState(!1);return r.useEffect(()=>{if(!t)return;a(!0);const n=setTimeout(()=>a(!1),1800);return()=>clearTimeout(n)},[t]),s?e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-[12.5px] text-muted-foreground","aria-live":"polite",children:[e.jsx(o,{className:"size-3.5 animate-spin","aria-hidden":"true"}),"Saving"]}):e.jsx("span",{className:"text-[12.5px] text-muted-foreground","aria-live":"polite",children:i?"Saved":""})}export{l as S};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,u as n,G as a,B as r}from"./index-
|
|
1
|
+
import{j as e,u as n,G as a,B as r}from"./index-DtF8YHqn.js";function i({error:s}){const t=n(),o=s instanceof Error?s.message:"Something went wrong.";return e.jsx(a,{children:e.jsxs("div",{className:"flex flex-col items-start gap-3",children:[e.jsx("h1",{className:"m-0 text-lg font-semibold",children:"Could not load the dashboard"}),e.jsx("p",{className:"m-0 text-muted-foreground",children:o}),e.jsx(r,{variant:"outline",size:"sm",onClick:()=>void t.invalidate(),children:"Try again"})]})})}const m=({error:s})=>e.jsx(i,{error:s});export{m as errorComponent};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{u as pt,a as gt,b as ft,c as I,r as o,d as z,e as le,g as ht,j as e,B as J,f as w,h as se,m as be,E as xt,i as ve,k as ge,l as mt,n as bt,o as ne,S as vt,p as Z,q as jt,L as _,s as yt,t as _e,M as St,v as wt,w as Ct,x as Nt,y as kt,O as Tt}from"./index-
|
|
1
|
+
import{u as pt,a as gt,b as ft,c as I,r as o,d as z,e as le,g as ht,j as e,B as J,f as w,h as se,m as be,E as xt,i as ve,k as ge,l as mt,n as bt,o as ne,S as vt,p as Z,q as jt,L as _,s as yt,t as _e,M as St,v as wt,w as Ct,x as Nt,y as kt,O as Tt}from"./index-DtF8YHqn.js";import{u as He}from"./useQuery-OgrKuHbc.js";import{T as Pt,i as ze,a as Rt,D as Mt,b as Et,c as Ot,X as Dt,d as It,e as At,f as _t,g as Ht,R as zt,p as Lt,h as $t,j as Bt,k as Ft,P as Ut,l as qt,u as Gt,m as Vt,n as Kt,o as Yt,q as Wt,r as Xt,s as Qt,t as Jt,v as Zt,w as es,x as ts,y as ss,z as ns,A as as,F as rs,B as os,C as is,E as Le,G as $e,H as Be,I as ls,J as ds,K as cs}from"./dialog-DdpHZobU.js";import{c as B,n as Fe,g as us,a as fe,t as ps,d as gs,i as fs,u as hs,b as de,L as xs,I as ms}from"./label-Dj8L94iS.js";import{g as he,u as bs,a as vs,b as js,s as ys,c as Ss,d as ws,e as Cs,f as Ns,h as ks,S as Ue,E as Q,D as ae,i as re,j as oe,k as je,l as ee,m as D,n as V,o as Ts,p as ce}from"./dropdown-menu-CB2L3nig.js";import{u as qe}from"./useRender-DOFVvGfR.js";import{A as Ps,a as Rs}from"./avatar-BKSc7tnv.js";import{S as Ms,i as Es,a as Os}from"./labels--UUyt9uB.js";import{u as Ge}from"./me-7-r9OeMR.js";import{L as te}from"./layout-grid-DuweH0Vl.js";import{U as xe}from"./users-CRiOyD0f.js";import{c as Ds}from"./update-duXzIzFS.js";import{P as Ve}from"./plus-CEWgXDLj.js";import{M as Is,S as As,a as _s}from"./sun-Bg7U-6Y0.js";import"./useBaseQuery-DSqwWD_O.js";import"./check-Ti2IOlgc.js";import"./CompositeItem-D1SCvKo_.js";import"./useValueChanged-B9k7l-mp.js";function Hs(t){const s=pt({warn:t?.router===void 0}),n=t?.router||s;return gt(n.stores.__store,ft(t,n))}/**
|
|
2
2
|
* @license lucide-react v1.39.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Q as g,T as f,U as p,o as v,j as e,B as m,V as N,L as P,p as j}from"./index-
|
|
1
|
+
import{Q as g,T as f,U as p,o as v,j as e,B as m,V as N,L as P,p as j}from"./index-DtF8YHqn.js";import{Q as y,u as b}from"./useBaseQuery-DSqwWD_O.js";import{P as w,S}from"./parts-CA4cbfy3.js";import{b as R,c as E,S as F}from"./labels--UUyt9uB.js";import{u as k}from"./me-7-r9OeMR.js";import"./card-Bz0VdsxC.js";var M=class extends y{constructor(s,n){super(s,n)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(s){s._type="infinite",super.setOptions(s)}getOptimisticResult(s){return s._type="infinite",super.getOptimisticResult(s)}fetchNextPage(s){return this.fetch({...s,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(s){return this.fetch({...s,meta:{fetchMore:{direction:"backward"}}})}createResult(s,n){const{state:i}=s,l=super.createResult(s,n),{isFetching:o,isRefetching:r,isError:u,isRefetchError:d}=l,t=i.fetchMeta?.fetchMore?.direction,c=u&&t==="forward",a=o&&t==="forward",h=u&&t==="backward",x=o&&t==="backward";return{...l,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:f(n,i.data),hasPreviousPage:g(n,i.data),isFetchNextPageError:c,isFetchingNextPage:a,isFetchPreviousPageError:h,isFetchingPreviousPage:x,isRefetchError:d&&!c&&!h,isRefetching:r&&!a&&!x}}};function A(s,n){return b(s,M)}const C=[{value:"unresolved",label:"Needs attention"},...E.map(s=>({value:s,label:F[s]})),{value:"all",label:"Everything"}];function O(s,n=new Date){const i=new Date(s),l=r=>new Date(r.getFullYear(),r.getMonth(),r.getDate()).getTime(),o=Math.round((l(n)-l(i))/864e5);return o<=0?"Today":o===1?"Yesterday":o<7?i.toLocaleDateString(void 0,{weekday:"long"}):i.toLocaleDateString(void 0,{day:"numeric",month:"long"})}function U(){const s=k(),{status:n="unresolved",site:i}=p.useSearch(),l=v({from:"/activity"}),o=t=>void l({search:c=>({...c,...t}),replace:!0}),r=A({queryKey:["activity",n,i??null],queryFn:({pageParam:t})=>j.activity({status:n,...i?{site:i}:{},...t?{cursor:t}:{}}),initialPageParam:"",getNextPageParam:t=>t.nextCursor??void 0,refetchOnWindowFocus:!0}),u=r.data?.pages.flatMap(t=>t.data)??[],d=[];for(const t of u){const c=O(t.updatedAt),a=d[d.length-1];a?.day===c?a.rows.push(t):d.push({day:c,rows:[t]})}return e.jsxs("div",{className:"flex flex-col gap-5 p-7",children:[e.jsx(w,{title:"Activity",sub:`Every site, newest first${i?"":" — all of them"}`}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[C.map(t=>e.jsx(m,{size:"sm",variant:n===t.value?"default":"outline",onClick:()=>o({status:t.value}),children:t.label},t.value)),e.jsx("div",{className:"flex-1"}),e.jsxs("label",{className:"flex items-center gap-2 text-[13px] text-muted-foreground",children:["Site",e.jsxs("select",{"aria-label":"Site",value:i??"",onChange:t=>o({site:t.target.value||void 0}),className:"h-8 rounded-md border border-input bg-background px-2.5 text-[13px] text-foreground",children:[e.jsx("option",{value:"",children:"All sites"}),s.projects.map(t=>e.jsx("option",{value:t.uid,children:t.name},t.uid))]})]})]}),r.isPending&&e.jsx(N,{rows:4}),r.isError&&e.jsx("p",{className:"m-0 text-[13px] text-destructive",children:"Could not read the feed. Reload to try again."}),r.isSuccess&&u.length===0&&e.jsx("p",{className:"m-0 text-[13px] text-muted-foreground",children:n==="resolved"?"Nothing has been resolved yet — this is where finished comments go.":n==="unresolved"?"Nothing needs attention. Every comment on every site is resolved.":"No comments yet on any site."}),d.map(({day:t,rows:c})=>e.jsxs("section",{className:"flex flex-col gap-2",children:[e.jsx("h2",{className:"m-0 text-[12px] font-medium uppercase tracking-wide text-muted-foreground",children:t}),e.jsx("ul",{className:"m-0 flex list-none flex-col gap-1.5 p-0",children:c.map(a=>e.jsx("li",{children:e.jsxs(P,{to:"/s/$site/comments",params:{site:a.site.uid},search:{thread:a.key},className:"flex flex-col gap-1 rounded-md border border-border px-3 py-2.5 no-underline transition-colors hover:bg-muted/60",children:[e.jsxs("span",{className:"flex flex-wrap items-center gap-x-2.5 gap-y-1 text-[13px]",children:[e.jsx(S,{status:a.status}),e.jsx("span",{className:"font-medium text-foreground",children:a.site.name}),e.jsx("code",{className:"font-mono text-[12px] text-muted-foreground",children:a.route}),e.jsx("span",{className:"flex-1"}),e.jsx("span",{className:"text-[12px] text-muted-foreground",children:R(a.updatedAt)})]}),a.latest?.body&&e.jsxs("span",{className:"line-clamp-2 text-[13px] text-foreground",children:[e.jsxs("span",{className:"text-muted-foreground",children:[a.latest.author??a.createdBy.name,": "]}),a.latest.body]}),e.jsxs("span",{className:"flex flex-wrap items-center gap-x-2 text-[12px] text-muted-foreground",children:[e.jsx("span",{className:"font-mono",children:a.key}),e.jsx("span",{children:"·"}),e.jsxs("span",{children:[a.commentCount," ",a.commentCount===1?"comment":"comments"]}),a.assignee&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"·"}),e.jsx("span",{children:a.assignee})]})]})]})},a.id))})]},t)),r.hasNextPage&&e.jsx("div",{children:e.jsx(m,{variant:"outline",size:"sm",disabled:r.isFetchingNextPage,onClick:()=>void r.fetchNextPage(),children:r.isFetchingNextPage?"Reading…":"Show older"})})]})}export{U as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as a,h as b,i as f,j as d,f as m}from"./index-
|
|
1
|
+
import{r as a,h as b,i as f,j as d,f as m}from"./index-DtF8YHqn.js";import{w as A}from"./dialog-DdpHZobU.js";const x=a.createContext(void 0);function z(){const e=a.useContext(x);if(e===void 0)throw new Error(b(13));return e}const g={imageLoadingStatus:()=>null},R=a.forwardRef(function(t,r){const{className:v,render:p,style:s,...c}=t,[n,o]=a.useState("idle"),i={imageLoadingStatus:n},u=a.useMemo(()=>({imageLoadingStatus:n,setImageLoadingStatus:o}),[n,o]),l=f("span",t,{state:i,ref:r,props:c,stateAttributesMapping:g});return d.jsx(x.Provider,{value:u,children:l})}),k=a.forwardRef(function(t,r){const{className:v,render:p,delay:s=0,style:c,...n}=t,{imageLoadingStatus:o}=z(),[i,u]=a.useState(s===0),l=A();return a.useEffect(()=>(s>0?l.start(s,()=>u(!0)):u(!0),l.clear),[l,s]),f("span",t,{state:{imageLoadingStatus:o},ref:r,props:n,stateAttributesMapping:g,enabled:o!=="loaded"&&(s===0||i)})});function h({className:e,size:t="default",...r}){return d.jsx(R,{"data-slot":"avatar","data-size":t,className:m("group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",e),...r})}function w({className:e,...t}){return d.jsx(k,{"data-slot":"avatar-fallback",className:m("flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",e),...t})}export{h as A,w as a};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as a,f as n,n as o}from"./index-
|
|
1
|
+
import{m as a,f as n,n as o}from"./index-DtF8YHqn.js";import{u as d}from"./useRender-DOFVvGfR.js";const s=o("group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",{variants:{variant:{default:"bg-primary text-primary-foreground [a]:hover:bg-primary/80",secondary:"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",destructive:"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",outline:"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",ghost:"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",link:"text-primary underline-offset-4 hover:underline"}},defaultVariants:{variant:"default"}});function v({className:r,variant:e="default",render:t,...i}){return d({defaultTagName:"span",props:a({className:n(s({variant:e}),r)},i),render:t,state:{slot:"badge",variant:e}})}export{v as B};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as s,f as t}from"./index-
|
|
1
|
+
import{j as s,f as t}from"./index-DtF8YHqn.js";function c({className:a,size:d="default",...r}){return s.jsx("div",{"data-slot":"card","data-size":d,className:t("group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",a),...r})}export{c as C};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as zn,aq as Z,k as Pe,ar as mt,ay as oe,aP as bt,r as l,aD as Jn,a3 as ke,e as q,l as Ze,d as N,h as zt,i as Ae,a4 as Qn,j as I,a5 as Jt,E as ve,aQ as Zn,a6 as Pt,g as et,au as ot,at as er,aR as tr,aS as Qt,aT as nr,az as rr,B as Zt,f as Fe}from"./index-
|
|
1
|
+
import{c as zn,aq as Z,k as Pe,ar as mt,ay as oe,aP as bt,r as l,aD as Jn,a3 as ke,e as q,l as Ze,d as N,h as zt,i as Ae,a4 as Qn,j as I,a5 as Jt,E as ve,aQ as Zn,a6 as Pt,g as et,au as ot,at as er,aR as tr,aS as Qt,aT as nr,az as rr,B as Zt,f as Fe}from"./index-DtF8YHqn.js";import{a as A,o as U,m as ge,c as Se,B as or,u as en,s as tn,y as yt,b as nn,w as rn,g as Ee,t as on,q as sn,n as sr,p as ir,i as ar}from"./label-Dj8L94iS.js";/**
|
|
2
2
|
* @license lucide-react v1.39.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as zn,r as u,i as Fe,E as tt,ao as qt,k as se,ap as $e,g as Pe,aq as ke,ar as We,as as on,at as lt,au as Et,av as Vo,aw as Un,ax as Wo,ay as rn,az as Kn,aA as Dt,aB as Gn,aC as En,l as Ct,a5 as Yn,d as de,a3 as Xn,e as pe,aD as qn,h as ze,a7 as jo,a4 as Qn,m as it,a6 as $o,j as Q,aE as zo,f as ut}from"./index-
|
|
1
|
+
import{c as zn,r as u,i as Fe,E as tt,ao as qt,k as se,ap as $e,g as Pe,aq as ke,ar as We,as as on,at as lt,au as Et,av as Vo,aw as Un,ax as Wo,ay as rn,az as Kn,aA as Dt,aB as Gn,aC as En,l as Ct,a5 as Yn,d as de,a3 as Xn,e as pe,aD as qn,h as ze,a7 as jo,a4 as Qn,m as it,a6 as $o,j as Q,aE as zo,f as ut}from"./index-DtF8YHqn.js";import{C as Uo}from"./check-Ti2IOlgc.js";import{i as Je,Q as Qt,w as _e,S as Jn,U as Zn,V as Ko,W as ft,Y as Tt,Z as eo,_ as to,a as Te,$ as Go,a0 as Mt,a1 as Yo,a2 as Xo,T as Jt,a3 as Lt,a4 as qo,a5 as Zt,v as Re,a6 as Qo,a7 as Jo,a8 as Zo,a9 as Cn,aa as Ut,ab as Tn,ac as Ne,ad as mt,ae as er,af as Nt,ag as Ht,ah as no,ai as sn,aj as tr,ak as nr,al as or,am as rr,C as sr,O as ir,A as oo,an as cr,B as ar,ao as lr,ap as ur,aq as fr,ar as dr,as as pr,z as gr,at as mr,au as hr,av as xr,N as yr,R as vr,p as Rr,aw as ro,j as br,P as wr,l as Er,ax as so,m as Cr,n as Tr,ay as Mr,az as Or,aA as Sr,q as Pr,aB as Ir,F as Ar,r as kr,o as Fr,aC as Dr,aD as Lr,aE as Nr,aF as Hr,aG as Br,aH as _r,s as Vr,t as Wr,aI as Mn,aJ as On,aK as jr}from"./dialog-DdpHZobU.js";import{t as cn,g as nt,c as ie,m as ct,o as Se,a as le,p as at,q as io,b as be,r as en,s as Ot,v as an,u as Bt,w as $r,x as st,k as zr,y as Sn,i as Ur,z as Kr}from"./label-Dj8L94iS.js";import{u as co,a as ao,C as Gr,b as Yr}from"./CompositeItem-D1SCvKo_.js";import{u as Xr}from"./useValueChanged-B9k7l-mp.js";/**
|
|
2
2
|
* @license lucide-react v1.39.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|