@volter/twin-sentry 0.1.36 → 1.0.0
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/README.md +21 -134
- package/api/spec/SOURCE.md +15 -0
- package/api/spec/doc-examples.json +12 -0
- package/api/spec/openapi.json.gz +0 -0
- package/api/spec/patches.json +5350 -0
- package/api/spec/sources.json +122 -0
- package/api/src/fetch.ts +18 -0
- package/api/src/generated/surface.gen.json +1 -0
- package/api/src/generated/ui.gen.json +1 -0
- package/api/src/index.ts +3 -0
- package/api/src/manifest.ts +136 -0
- package/api/src/semantics/api.ts +246 -0
- package/api/src/semantics/around.ts +36 -0
- package/api/src/semantics/doors.ts +50 -0
- package/api/src/semantics/index.ts +19 -0
- package/api/src/semantics/shared.ts +35 -0
- package/api/src/semantics/states.ts +17 -0
- package/dist/api/spec/SOURCE.md +15 -0
- package/dist/api/spec/doc-examples.json +12 -0
- package/dist/api/spec/openapi.json.gz +0 -0
- package/dist/api/spec/patches.json +5350 -0
- package/dist/api/spec/sources.json +122 -0
- package/dist/api/src/fetch.d.ts +2 -0
- package/dist/api/src/fetch.js +17 -0
- package/dist/api/src/fetch.ts +18 -0
- package/dist/api/src/generated/surface.gen.json +1 -0
- package/dist/api/src/generated/ui.gen.json +1 -0
- package/dist/api/src/index.d.ts +2 -0
- package/dist/api/src/index.js +3 -0
- package/dist/api/src/index.ts +3 -0
- package/dist/api/src/manifest.d.ts +2 -0
- package/dist/api/src/manifest.js +135 -0
- package/dist/api/src/manifest.ts +136 -0
- package/dist/api/src/semantics/api.d.ts +13 -0
- package/dist/api/src/semantics/api.js +267 -0
- package/dist/api/src/semantics/api.ts +246 -0
- package/dist/api/src/semantics/around.d.ts +2 -0
- package/dist/api/src/semantics/around.js +41 -0
- package/dist/api/src/semantics/around.ts +36 -0
- package/dist/api/src/semantics/doors.d.ts +8 -0
- package/dist/api/src/semantics/doors.js +39 -0
- package/dist/api/src/semantics/doors.ts +50 -0
- package/dist/api/src/semantics/index.d.ts +2 -0
- package/dist/api/src/semantics/index.js +15 -0
- package/dist/api/src/semantics/index.ts +19 -0
- package/dist/api/src/semantics/shared.d.ts +15 -0
- package/dist/api/src/semantics/shared.js +27 -0
- package/dist/api/src/semantics/shared.ts +35 -0
- package/dist/api/src/semantics/states.d.ts +24 -0
- package/dist/api/src/semantics/states.js +17 -0
- package/dist/api/src/semantics/states.ts +17 -0
- package/dist/generated/pack-facts.json +87 -0
- package/dist/ingest/spec/SOURCE.md +30 -0
- package/dist/ingest/spec/authentication.mdx.gz +0 -0
- package/dist/ingest/spec/compression.mdx.gz +0 -0
- package/dist/ingest/spec/doc-examples.json +216 -0
- package/dist/ingest/spec/envelope-items.mdx.gz +0 -0
- package/dist/ingest/spec/envelopes.mdx.gz +0 -0
- package/dist/ingest/spec/openapi.json +178 -0
- package/dist/ingest/spec/rate-limiting.mdx.gz +0 -0
- package/dist/ingest/spec/sources.json +25 -0
- package/dist/ingest/spec/transport.mdx.gz +0 -0
- package/dist/ingest/spec/write-spec.ts +192 -0
- package/dist/ingest/src/fetch.d.ts +2 -0
- package/dist/ingest/src/fetch.js +15 -0
- package/dist/ingest/src/fetch.ts +16 -0
- package/dist/ingest/src/generated/surface.gen.json +1 -0
- package/dist/ingest/src/generated/ui.gen.json +1 -0
- package/dist/ingest/src/index.d.ts +2 -0
- package/dist/ingest/src/index.js +3 -0
- package/dist/ingest/src/index.ts +3 -0
- package/dist/ingest/src/manifest.d.ts +2 -0
- package/dist/ingest/src/manifest.js +34 -0
- package/dist/ingest/src/manifest.ts +39 -0
- package/dist/ingest/src/semantics/api.d.ts +2 -0
- package/dist/ingest/src/semantics/api.js +240 -0
- package/dist/ingest/src/semantics/api.ts +188 -0
- package/dist/ingest/src/semantics/around.d.ts +2 -0
- package/dist/ingest/src/semantics/around.js +6 -0
- package/dist/ingest/src/semantics/around.ts +7 -0
- package/dist/ingest/src/semantics/index.d.ts +2 -0
- package/dist/ingest/src/semantics/index.js +4 -0
- package/dist/ingest/src/semantics/index.ts +8 -0
- package/dist/ingest/src/semantics/shared.d.ts +4 -0
- package/dist/ingest/src/semantics/shared.js +2 -0
- package/dist/ingest/src/semantics/shared.ts +7 -0
- package/dist/ingest/src/semantics/states.d.ts +1 -0
- package/dist/ingest/src/semantics/states.js +2 -0
- package/dist/ingest/src/semantics/states.ts +2 -0
- package/dist/journeys/coverage.json +205 -0
- package/dist/journeys/customer-life.json +923 -0
- package/dist/journeys/customer-life.outline.md +51 -0
- package/dist/journeys/decisions.json +170 -0
- package/dist/journeys/demand.json +136 -0
- package/dist/journeys/score.json +231 -0
- package/dist/journeys/unreachable.json +29 -0
- package/dist/journeys/vendor-examples.json +474 -0
- package/dist/spec/sources.json +76 -0
- package/dist/src/cli.js +12 -27
- package/dist/src/fetch.d.ts +2 -0
- package/dist/src/fetch.js +9 -0
- package/dist/src/index.d.ts +5 -15
- package/dist/src/index.js +12 -75
- package/dist/src/manifest.d.ts +2 -0
- package/dist/src/manifest.js +34 -0
- package/dist/src/semantics/shared.d.ts +87 -0
- package/dist/src/semantics/shared.js +411 -0
- package/dist/src/server.d.ts +7 -0
- package/dist/src/server.js +7 -0
- package/generated/pack-facts.json +87 -0
- package/ingest/spec/SOURCE.md +30 -0
- package/ingest/spec/authentication.mdx.gz +0 -0
- package/ingest/spec/compression.mdx.gz +0 -0
- package/ingest/spec/doc-examples.json +216 -0
- package/ingest/spec/envelope-items.mdx.gz +0 -0
- package/ingest/spec/envelopes.mdx.gz +0 -0
- package/ingest/spec/openapi.json +178 -0
- package/ingest/spec/rate-limiting.mdx.gz +0 -0
- package/ingest/spec/sources.json +25 -0
- package/ingest/spec/transport.mdx.gz +0 -0
- package/ingest/spec/write-spec.ts +192 -0
- package/ingest/src/fetch.ts +16 -0
- package/ingest/src/generated/surface.gen.json +1 -0
- package/ingest/src/generated/ui.gen.json +1 -0
- package/ingest/src/index.ts +3 -0
- package/ingest/src/manifest.ts +39 -0
- package/ingest/src/semantics/api.ts +188 -0
- package/ingest/src/semantics/around.ts +7 -0
- package/ingest/src/semantics/index.ts +8 -0
- package/ingest/src/semantics/shared.ts +7 -0
- package/ingest/src/semantics/states.ts +2 -0
- package/journeys/coverage.json +205 -0
- package/journeys/customer-life.json +923 -0
- package/journeys/customer-life.outline.md +51 -0
- package/journeys/decisions.json +170 -0
- package/journeys/demand.json +136 -0
- package/journeys/score.json +231 -0
- package/journeys/unreachable.json +29 -0
- package/journeys/vendor-examples.json +474 -0
- package/package.json +16 -42
- package/spec/sources.json +76 -0
- package/src/cli.ts +12 -24
- package/src/fetch.ts +10 -0
- package/src/index.ts +12 -143
- package/src/manifest.ts +40 -0
- package/src/semantics/shared.ts +443 -0
- package/src/server.ts +8 -0
- package/client/sentry-mirror.css +0 -99
- package/client/sentry-mirror.tsx +0 -352
- package/dist/client/sentry-mirror.bundle.js +0 -388
- package/dist/client/sentry-mirror.css +0 -99
- package/dist/client/sentry-mirror.d.ts +0 -17
- package/dist/client/sentry-mirror.js +0 -156
- package/dist/client/sentry-mirror.tsx +0 -352
- package/dist/src/sentry-budget.d.ts +0 -50
- package/dist/src/sentry-budget.js +0 -145
- package/dist/src/sentry-capabilities.d.ts +0 -3
- package/dist/src/sentry-capabilities.js +0 -1180
- package/dist/src/sentry-conformance.d.ts +0 -22
- package/dist/src/sentry-conformance.js +0 -97
- package/dist/src/sentry-connector.d.ts +0 -77
- package/dist/src/sentry-connector.js +0 -226
- package/dist/src/sentry-events.d.ts +0 -54
- package/dist/src/sentry-events.js +0 -132
- package/dist/src/sentry-ingest.d.ts +0 -137
- package/dist/src/sentry-ingest.js +0 -387
- package/dist/src/sentry-mirror-ui.d.ts +0 -38
- package/dist/src/sentry-mirror-ui.js +0 -162
- package/dist/src/sentry-perform-harness.d.ts +0 -9
- package/dist/src/sentry-perform-harness.js +0 -20
- package/dist/src/sentry-server.d.ts +0 -14
- package/dist/src/sentry-server.js +0 -27
- package/dist/src/sentry-twin.d.ts +0 -17
- package/dist/src/sentry-twin.js +0 -1739
- package/dist/test-fixtures/sentry-openapi-operations.SOURCE.md +0 -24
- package/dist/test-fixtures/sentry-openapi-operations.json +0 -1837
- package/src/sentry-budget.ts +0 -171
- package/src/sentry-capabilities.ts +0 -1222
- package/src/sentry-conformance.ts +0 -110
- package/src/sentry-connector.ts +0 -260
- package/src/sentry-events.ts +0 -172
- package/src/sentry-ingest.ts +0 -471
- package/src/sentry-mirror-ui.ts +0 -162
- package/src/sentry-perform-harness.ts +0 -19
- package/src/sentry-server.ts +0 -35
- package/src/sentry-twin.ts +0 -1615
- package/test-fixtures/sentry-openapi-operations.SOURCE.md +0 -24
- package/test-fixtures/sentry-openapi-operations.json +0 -1837
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"https://raw.githubusercontent.com/getsentry/sentry/2efdd4760a75a3d395e3534b7f66a7fbb0c3f22e/src/sentry/api/serializers/models/project_key.py": {
|
|
3
|
+
"status": 200,
|
|
4
|
+
"checked": "2026-10-03",
|
|
5
|
+
"quotes": {
|
|
6
|
+
"ProjectKeySerializerResponse": true
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
"https://raw.githubusercontent.com/getsentry/sentry/2efdd4760a75a3d395e3534b7f66a7fbb0c3f22e/src/sentry/features/permanent.py": {
|
|
10
|
+
"status": 200,
|
|
11
|
+
"checked": "2026-10-03",
|
|
12
|
+
"quotes": {
|
|
13
|
+
"organizations:advanced-search": true,
|
|
14
|
+
"organizations:change-alerts": true,
|
|
15
|
+
"organizations:crash-rate-alerts": true,
|
|
16
|
+
"organizations:custom-symbol-sources": true,
|
|
17
|
+
"organizations:data-forwarding": true,
|
|
18
|
+
"organizations:discover-basic": true,
|
|
19
|
+
"organizations:discover-query": true,
|
|
20
|
+
"organizations:event-attachments": true,
|
|
21
|
+
"organizations:integrations-alert-rule": true,
|
|
22
|
+
"organizations:integrations-chat-unfurl": true,
|
|
23
|
+
"organizations:integrations-codeowners": true,
|
|
24
|
+
"organizations:integrations-enterprise-alert-rule": true,
|
|
25
|
+
"organizations:integrations-enterprise-incident-management": true,
|
|
26
|
+
"organizations:integrations-event-hooks": true,
|
|
27
|
+
"organizations:integrations-incident-management": true,
|
|
28
|
+
"organizations:integrations-issue-basic": true,
|
|
29
|
+
"organizations:integrations-issue-sync": true,
|
|
30
|
+
"organizations:integrations-scm-multi-org": true,
|
|
31
|
+
"organizations:integrations-stacktrace-link": true,
|
|
32
|
+
"organizations:integrations-ticket-rules": true,
|
|
33
|
+
"organizations:integrations-vercel": true,
|
|
34
|
+
"organizations:performance-view": true,
|
|
35
|
+
"organizations:relay": true,
|
|
36
|
+
"organizations:sso-basic": true,
|
|
37
|
+
"organizations:sso-saml2": true,
|
|
38
|
+
"organizations:team-insights": true,
|
|
39
|
+
"organizations:team-roles": true,
|
|
40
|
+
"organizations:uptime": true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"https://raw.githubusercontent.com/getsentry/sentry/2efdd4760a75a3d395e3534b7f66a7fbb0c3f22e/src/sentry/features/temporary.py": {
|
|
44
|
+
"status": 200,
|
|
45
|
+
"checked": "2026-10-03",
|
|
46
|
+
"quotes": {
|
|
47
|
+
"organizations:dashboards-basic": true,
|
|
48
|
+
"organizations:dashboards-edit": true,
|
|
49
|
+
"organizations:insight-modules": true,
|
|
50
|
+
"organizations:invite-members": true,
|
|
51
|
+
"organizations:sentry-app-schema-form-migration": true,
|
|
52
|
+
"organizations:session-replay-ui": true
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"https://raw.githubusercontent.com/getsentry/sentry/2efdd4760a75a3d395e3534b7f66a7fbb0c3f22e/src/sentry/models/projectkey.py": {
|
|
56
|
+
"status": 200,
|
|
57
|
+
"checked": "2026-10-03",
|
|
58
|
+
"quotes": {
|
|
59
|
+
"secret_key = ProjectKey.generate_api_key()": true
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"https://raw.githubusercontent.com/getsentry/sentry/2efdd4760a75a3d395e3534b7f66a7fbb0c3f22e/src/sentry/projectoptions/defaults.py": {
|
|
63
|
+
"status": 200,
|
|
64
|
+
"checked": "2026-10-03",
|
|
65
|
+
"quotes": {
|
|
66
|
+
"sentry:default_loader_version": true
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"https://raw.githubusercontent.com/getsentry/sentry/2efdd4760a75a3d395e3534b7f66a7fbb0c3f22e/src/sentry/utils/numbers.py": {
|
|
70
|
+
"status": 200,
|
|
71
|
+
"checked": "2026-10-03",
|
|
72
|
+
"quotes": {
|
|
73
|
+
"0123456789ABCDEFGHJKMNPQRSTVWXYZ": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
package/dist/src/cli.js
CHANGED
|
@@ -1,36 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// world-sentry CLI: serve the Sentry API twin (ingestion + Web API), the dashboard mirror
|
|
4
|
-
// UI, or run conformance. (Conformance lives in dev-tooling; cli.ts must not import it, so
|
|
5
|
-
// it's loaded lazily only when the `conformance` command is invoked.)
|
|
2
|
+
// world-sentry: serve the sentry twin.
|
|
6
3
|
import { hasFlag, optionValue } from '@volter/world-core/args';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { defaultDsn } from "./sentry-ingest.js";
|
|
4
|
+
import { keepProcessAlive } from '@volter/world-core/lifecycle';
|
|
5
|
+
import { createSentryTwinServer } from "./server.js";
|
|
10
6
|
const [cmd, ...rest] = process.argv.slice(2);
|
|
11
7
|
const port = Number(optionValue(rest, '--port', '0')) || undefined;
|
|
12
8
|
const root = optionValue(rest, '--root') || undefined;
|
|
13
|
-
const readOnly = hasFlag(rest, '--read-only');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
const readOnly = hasFlag(rest, '--read-only');
|
|
10
|
+
// the World's managed Postgres, which the runtime binds a pack declaring managedDatabase to
|
|
11
|
+
const database = optionValue(rest, '--database') || undefined;
|
|
12
|
+
// the World's scenario file, for a model vendor's turns
|
|
13
|
+
const scenarioPath = optionValue(rest, '--scenario') || undefined;
|
|
14
|
+
if (cmd === 'serve' || cmd === undefined) {
|
|
15
|
+
const s = await createSentryTwinServer({ readOnly, ...(root ? { root } : {}), ...(port ? { port } : {}), ...(database ? { database } : {}), ...(scenarioPath ? { scenarioPath } : {}) });
|
|
16
|
+
process.stdout.write(`sentry twin${readOnly ? ' [read-only]' : ''} at http://127.0.0.1:${s.port}\n`);
|
|
19
17
|
await keepProcessAlive();
|
|
20
18
|
}
|
|
21
|
-
else if (cmd === 'mirror') {
|
|
22
|
-
const s = await createSentryMirrorServer({ ...(root ? { root } : {}), ...(port ? { port } : {}) });
|
|
23
|
-
process.stdout.write(`sentry mirror UI (dashboard) at http://127.0.0.1:${s.port}\n`);
|
|
24
|
-
await keepProcessAlive();
|
|
25
|
-
}
|
|
26
|
-
else if (cmd === 'conformance') {
|
|
27
|
-
// dev-only: dynamic import so the conformance module never enters the runtime entrypoints.
|
|
28
|
-
const { checkSentryConformance } = await import("./sentry-conformance.js");
|
|
29
|
-
const report = await checkSentryConformance({ ...(root ? { root } : {}) });
|
|
30
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
31
|
-
if (!report.ok)
|
|
32
|
-
process.exitCode = 1;
|
|
33
|
-
}
|
|
34
19
|
else {
|
|
35
|
-
process.stdout.write('Usage: world-sentry serve
|
|
20
|
+
process.stdout.write('Usage: world-sentry serve [--port N] [--root DIR] [--read-only] [--database URL] [--scenario FILE]\n');
|
|
36
21
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// GENERATED by scripts/create-pack.ts (--init, --index): a fixed file. The kernel serves the vendor's discovery door and
|
|
2
|
+
// sends each request to the lane its manifest's routes name (architecture, "Other wires: lanes").
|
|
3
|
+
import { createVendorFetch } from '@volter/world-core';
|
|
4
|
+
import { manifest } from "./manifest.js";
|
|
5
|
+
import { createApiLaneFetch, manifest as api_manifest } from "../api/src/index.js";
|
|
6
|
+
import { createIngestLaneFetch, manifest as ingest_manifest } from "../ingest/src/index.js";
|
|
7
|
+
export function createSentryFetch(options = {}) {
|
|
8
|
+
return createVendorFetch(manifest, { "api": { fetch: createApiLaneFetch(options), manifest: api_manifest }, "ingest": { fetch: createIngestLaneFetch(options), manifest: ingest_manifest } });
|
|
9
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export
|
|
6
|
-
export { computeSentrySignature, constructSentryWebhook, emitIssueAlert, listAlertRules, registerAlertRule, SentrySignatureVerificationError, verifySentrySignature, } from './sentry-events.js';
|
|
7
|
-
export type { AlertTrigger, SentryWebhook, SentryWebhookAction, SentryWebhookDelivery } from './sentry-events.js';
|
|
8
|
-
export { liveSentryExecute, mapIssue, mapProject, mapRelease, pullSentryIssues, pullSentryProjects, pullSentryReleases, pushSentryAction, sentryRequestForAction, syncSentryFromReal, } from './sentry-connector.js';
|
|
9
|
-
export type { SentryExecute, LiveSentryOptions } from './sentry-connector.js';
|
|
10
|
-
export { SENTRY_BUDGET_CEILING, SENTRY_BUDGET_MAX_RETRY_AFTER_S, SENTRY_BUDGET_WINDOW_MS, SENTRY_CALL_WEIGHTS, SENTRY_RATE_BUDGET, SentryBudget, SentryBudgetError, sentryBudgetPath, sentryCallWeight, } from './sentry-budget.js';
|
|
11
|
-
export type { SentryBudgetErrorKind, SentryBudgetOptions, SentryBudgetReservation, SentryBudgetSnapshot } from './sentry-budget.js';
|
|
12
|
-
export { buildSentryMirrorClient, createSentryMirrorServer, eventTags, formatCount, latestStacktrace, levelTone, sentryMirrorHtml, statusTone, timeAgo, } from './sentry-mirror-ui.js';
|
|
13
|
-
export type { IssueRow, StackFrame } from './sentry-mirror-ui.js';
|
|
14
|
-
import type { TwinPack } from '@volter/world-core';
|
|
15
|
-
export declare const pack: TwinPack;
|
|
1
|
+
import { manifest } from './manifest.js';
|
|
2
|
+
export { createSentryFetch } from './fetch.js';
|
|
3
|
+
export { createSentryTwinServer } from './server.js';
|
|
4
|
+
export { manifest };
|
|
5
|
+
export declare const pack: import("@volter/world-core").PackDescriptor;
|
package/dist/src/index.js
CHANGED
|
@@ -1,75 +1,12 @@
|
|
|
1
|
-
// @volter/twin-sentry — the
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
|
|
13
|
-
// request through. The MECHANISM is the kernel's shared, vendor-agnostic `RateBudget`; what lives
|
|
14
|
-
// here is Sentry's DECLARATION (window/ceiling/per-endpoint weights) plus the vendor-bound
|
|
15
|
-
// bindings. Exported so an operator can inspect spend (`snapshot`) and so a caller can catch
|
|
16
|
-
// `SentryBudgetError` by type; there is deliberately no export that disables the guard.
|
|
17
|
-
export { SENTRY_BUDGET_CEILING, SENTRY_BUDGET_MAX_RETRY_AFTER_S, SENTRY_BUDGET_WINDOW_MS, SENTRY_CALL_WEIGHTS, SENTRY_RATE_BUDGET, SentryBudget, SentryBudgetError, sentryBudgetPath, sentryCallWeight, } from "./sentry-budget.js";
|
|
18
|
-
export { buildSentryMirrorClient, createSentryMirrorServer, eventTags, formatCount, latestStacktrace, levelTone, sentryMirrorHtml, statusTone, timeAgo, } from "./sentry-mirror-ui.js";
|
|
19
|
-
import { SENTRY_RATE_BUDGET as RATE_BUDGET } from "./sentry-budget.js";
|
|
20
|
-
import { performSentryAction, syncSentryFromRemote } from "./sentry-connector.js";
|
|
21
|
-
export const pack = {
|
|
22
|
-
// PROTOCOL 2 (docs/contributing/architecture.md#protocol-2-the-pack-is-a-plugin): the pack is a plugin — its wire, its tree, and its half of the real
|
|
23
|
-
// state system. Moved 2026-09-08. TRIAGE is what crosses to Sentry — an issue resolved, assigned, muted;
|
|
24
|
-
// everything else this twin holds is something Sentry told it.
|
|
25
|
-
protocol: '2',
|
|
26
|
-
refresh: { every: '2m', webhook: true, onDemand: { atMost: '30s' } },
|
|
27
|
-
stateSystem: { perform: performSentryAction, refresh: syncSentryFromRemote },
|
|
28
|
-
// the round trip: an organization, then a project in it — the two things a Sentry account is made of
|
|
29
|
-
// the round trip: an organization, a team in it, then a project under that team — Sentry's own create
|
|
30
|
-
// path for a project is /teams/:org/:team/projects/, not the organization
|
|
31
|
-
roundTrip: [
|
|
32
|
-
{ method: 'POST', path: '/api/0/organizations/', body: { name: 'Round Trip', slug: 'round-trip' }, headers: { authorization: 'Bearer round-trip' } },
|
|
33
|
-
{ method: 'POST', path: '/api/0/organizations/round-trip/teams/', body: { name: 'Round Trip', slug: 'round-trip' }, headers: { authorization: 'Bearer round-trip' } },
|
|
34
|
-
{ method: 'POST', path: '/api/0/teams/round-trip/round-trip/projects/', body: { name: 'Round Trip', platform: 'node' }, headers: { authorization: 'Bearer round-trip' } },
|
|
35
|
-
// a project's slug is unique inside its org, so the create above rightly refuses a second one on a
|
|
36
|
-
// branch that already has it — the vendor's own truth. The last write is therefore the one a world
|
|
37
|
-
// repeats freely: triage on the project's own issue stream.
|
|
38
|
-
{ method: 'PUT', path: '/api/0/projects/round-trip/round-trip/', body: { platform: 'node', digestsMinDelay: 60 }, headers: { authorization: 'Bearer round-trip' } },
|
|
39
|
-
],
|
|
40
|
-
parityOrigin: 'http://twin',
|
|
41
|
-
vendor: 'sentry',
|
|
42
|
-
// The SAME object sentry-budget.ts declares at module load — one source of truth, so registering
|
|
43
|
-
// the pack and importing the connector can never arm two different ceilings.
|
|
44
|
-
rateBudget: RATE_BUDGET,
|
|
45
|
-
transport: 'rest',
|
|
46
|
-
archetype: 'crud',
|
|
47
|
-
bin: 'world-sentry',
|
|
48
|
-
resources: ['organization', 'team', 'project', 'project_key', 'issue', 'event', 'event_attachment', 'session', 'project_ownership', 'codeowners', 'project_filter', 'release', 'release_file', 'deploy', 'alert_rule', 'metric_alert', 'org_integration'],
|
|
49
|
-
specSource: 'Sentry API reference (https://docs.sentry.io/api/) — ingest store/envelope + Web API /api/0/',
|
|
50
|
-
description: 'Sentry REST twin — SDK ingestion → grouped issues, Web API, signed alert webhooks, dashboard mirror.',
|
|
51
|
-
// Adoption + interception, moved off the central maps unchanged (descriptor-first back-migration, adding-a-twin.md §3,
|
|
52
|
-
// 2026-08-31). The four canonical clients plus the further first-party @sentry
|
|
53
|
-
// framework SDKs of the same ingest surface — battery-observed: sentry was the single
|
|
54
|
-
// most-missed vendor, 13 repos, largely via these — and the whole `@sentry/` scope so a
|
|
55
|
-
// satellite package like `@sentry/cli` still detects.
|
|
56
|
-
adoption: {
|
|
57
|
-
// Sentry's official Python SDK - the one distribution behind every Python integration.
|
|
58
|
-
pypi: ['sentry-sdk'],
|
|
59
|
-
sdks: [
|
|
60
|
-
'@sentry/node', '@sentry/browser', '@sentry/react', '@sentry/nextjs',
|
|
61
|
-
'@sentry/vue', '@sentry/sveltekit', '@sentry/astro', '@sentry/remix',
|
|
62
|
-
'@sentry/electron', '@sentry/react-native',
|
|
63
|
-
],
|
|
64
|
-
scopes: ['@sentry/'],
|
|
65
|
-
// 'APPSMITHSENTRY' — appsmith names its DSN APPSMITH_SENTRY_DSN, an app-prefixed Sentry
|
|
66
|
-
// credential for the same ingest surface (ladder classification 2026-09-02).
|
|
67
|
-
envStems: ['SENTRY', 'APPSMITHSENTRY'],
|
|
68
|
-
},
|
|
69
|
-
// sentry.io (the web/REST API) plus the per-organization DSN ingest hosts
|
|
70
|
-
// (`o<org-id>.ingest.sentry.io`), which need the suffix form.
|
|
71
|
-
hosts: [{ host: 'sentry.io' }, { suffix: '.ingest.sentry.io' }],
|
|
72
|
-
// The @sentry/node SDK POSTs to <dsn-host>/api/:projectId/envelope/; the dashboard hits
|
|
73
|
-
// /api/0/. The dev proxy forwards both prefixes to the twin and strips the sentry.io host.
|
|
74
|
-
browserRouting: { apiPathPrefix: '/api/', loaderHost: 'https://sentry.io' },
|
|
75
|
-
};
|
|
1
|
+
// @volter/twin-sentry — the sentry twin (Protocol 3). A fixed file (create-pack): the descriptor is the manifest's, and the
|
|
2
|
+
// kernel derives the vendor-backed half from the generated surface (architecture, "The real-system adapters").
|
|
3
|
+
import { packOf, registerPack } from '@volter/world-core';
|
|
4
|
+
import { manifest } from "./manifest.js";
|
|
5
|
+
import { manifest as apiManifest } from "../api/src/manifest.js";
|
|
6
|
+
import apiSurface from '../api/src/generated/surface.gen.json' with { type: 'json' };
|
|
7
|
+
import { manifest as ingestManifest } from "../ingest/src/manifest.js";
|
|
8
|
+
import ingestSurface from '../ingest/src/generated/surface.gen.json' with { type: 'json' };
|
|
9
|
+
export { createSentryFetch } from "./fetch.js";
|
|
10
|
+
export { createSentryTwinServer } from "./server.js";
|
|
11
|
+
export { manifest };
|
|
12
|
+
export const pack = registerPack(packOf(manifest, { "api": { manifest: apiManifest, surface: apiSurface }, "ingest": { manifest: ingestManifest, surface: ingestSurface } }));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const manifest = {
|
|
2
|
+
vendor: 'sentry',
|
|
3
|
+
discovery: {
|
|
4
|
+
twinOf: 'Sentry: the envelopes its SDKs send (errors, transactions, sessions, replays, profiles, cron check-ins, feedback, logs, metrics), and its web API for events, issues, releases and source maps',
|
|
5
|
+
stores: 'organizations, projects and client keys, auth tokens (by their SHA-256), events and issues, and every other envelope item; releases and artifact bundles',
|
|
6
|
+
},
|
|
7
|
+
lanes: {
|
|
8
|
+
routes: [
|
|
9
|
+
{ lane: 'ingest', host: '(^|\\.)ingest(\\.[a-z]+)?\\.sentry\\.io$' },
|
|
10
|
+
{ lane: 'api', host: '^([a-z]+\\.)?sentry\\.io$' },
|
|
11
|
+
],
|
|
12
|
+
default: 'api',
|
|
13
|
+
},
|
|
14
|
+
descriptor: {
|
|
15
|
+
protocol: '3',
|
|
16
|
+
transport: 'rest',
|
|
17
|
+
archetype: 'crud',
|
|
18
|
+
bin: 'world-sentry',
|
|
19
|
+
resources: ['organization', 'project', 'project_key', 'event', 'issue', 'release', 'monitor', 'check_in'],
|
|
20
|
+
specSource: "Sentry's OpenAPI document (api/spec, sentry-api-schema 98ec014, patched with evidence) and its SDK developer documentation's envelope endpoint (ingest/spec)",
|
|
21
|
+
description: 'Sentry twin — the envelope endpoint every SDK sends to (events grouped into issues, transactions, sessions, replays, profiles, check-ins, feedback, logs, metrics), and release and source-map APIs used by Cal.com, Postiz and Rallly, account project/key setup, and core vendor-backed reads.',
|
|
22
|
+
adoption: { sdks: ['@sentry/astro', '@sentry/browser', '@sentry/electron', '@sentry/nextjs', '@sentry/node', '@sentry/nestjs', '@sentry/react', '@sentry/react-native', '@sentry/remix', '@sentry/sveltekit', '@sentry/vue', '@sentry/cli'], pypi: ['sentry-sdk'], envStems: ['APPSMITHSENTRY', 'SENTRY'] },
|
|
23
|
+
hosts: [{ host: 'sentry.io' }, { host: 'us.sentry.io' }, { host: 'de.sentry.io' }, { suffix: '.ingest.sentry.io' }, { suffix: '.ingest.us.sentry.io' }, { suffix: '.ingest.de.sentry.io' }],
|
|
24
|
+
endpointEnvNone: "an SDK sends to its DSN's host and sentry-cli to SENTRY_URL (sentry.io by default); the DSN the World issues names the World's ingest host, claimed by the host rules",
|
|
25
|
+
// Bootstrap: account sign-up, first credential and the project/key named by this env, stable at every boot.
|
|
26
|
+
credentialDoor: {
|
|
27
|
+
path: '/_twin/app-credentials', body: {},
|
|
28
|
+
fill: {
|
|
29
|
+
SENTRY_DSN: 'dsn', NEXT_PUBLIC_SENTRY_DSN: 'dsn', NEXT_PUBLIC_SENTRY_DSN_CLIENT: 'dsn', SENTRY_FRONT_DSN: 'dsn', SENTRY_DSN_API: 'dsn', VITE_SENTRY_DSN: 'dsn', EXPO_PUBLIC_SENTRY_DSN: 'dsn',
|
|
30
|
+
SENTRY_AUTH_TOKEN: 'auth_token', SENTRY_ORG: 'org', SENTRY_ORGANIZATION: 'org', SENTRY_PROJECT: 'project',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { HandlerContext } from '@volter/world-core';
|
|
2
|
+
type Reader = Pick<HandlerContext, 'row' | 'rowsRaw' | 'own'>;
|
|
3
|
+
export type Row = Record<string, unknown>;
|
|
4
|
+
/** An organization, made the first time (sentry.io's sign-up names it). */
|
|
5
|
+
export declare function makeOrg(ctx: HandlerContext, slug: string, name: string): Promise<Row>;
|
|
6
|
+
/** A project of an organization with its default client key (the project's creation makes one). */
|
|
7
|
+
export declare function makeProject(ctx: HandlerContext, org: Row, slug: string, platform: string | null): Promise<Row>;
|
|
8
|
+
/** An organization auth token, made on Settings > Auth Tokens: its value shown once. Its scopes are the organization
|
|
9
|
+
* token's fixed set ("org:ci": releases and source maps, and reading the organization). */
|
|
10
|
+
export declare function makeOrgToken(ctx: HandlerContext, org: Row, name: string, scopes?: string[]): Promise<string>;
|
|
11
|
+
/** A token the organization holds by its name, answered again only while its derived value still matches its hash. */
|
|
12
|
+
export declare function heldOrgToken(ctx: HandlerContext, org: Row, name: string): Promise<string | undefined>;
|
|
13
|
+
/** A personal token (User Settings > Personal Tokens): `sntryu_` and 64 hexadecimal digits, with the scopes chosen when it
|
|
14
|
+
* is made, acting on the organizations its user belongs to (here, the one named). */
|
|
15
|
+
export declare function makePersonalToken(ctx: HandlerContext, org: Row, name: string, scopes: string[]): Promise<string>;
|
|
16
|
+
/** The token a request's `Authorization: Bearer` names, if the World issued it and it is not revoked. */
|
|
17
|
+
export declare function bearerToken(ctx: Pick<HandlerContext, 'row' | 'crypto' | 'call'>): Row | undefined;
|
|
18
|
+
/** Whether a token's scopes grant one: the scope itself, one its `org:ci` implies, or the same resource's write or
|
|
19
|
+
* admin (a `:write` scope reads, an `:admin` one writes and reads). */
|
|
20
|
+
export declare function grants(token: Row, scope: string): boolean;
|
|
21
|
+
/** An event's time: its `timestamp` (RFC 3339 or seconds since the epoch), else when it was received. */
|
|
22
|
+
export declare function eventTime(payload: Row, received: string): string;
|
|
23
|
+
/** An event's title, culprit, location and metadata, as Sentry derives them for its kind. Where the documentation stops:
|
|
24
|
+
* Sentry's own derivation (its event types' `get_title` and `get_location`) is code, not a page; these follow its
|
|
25
|
+
* answers' forms: `<Type>: <value>` for an error, the message for a message event, the transaction's name for one. */
|
|
26
|
+
export declare function derive(payload: Row, type: string): {
|
|
27
|
+
title: string;
|
|
28
|
+
culprit: string;
|
|
29
|
+
location: string | null;
|
|
30
|
+
metadata: Row;
|
|
31
|
+
};
|
|
32
|
+
/** The hash an error groups by: its fingerprint when the SDK sends one of its own, else its exception's type and its
|
|
33
|
+
* in-app frames (or its type and value, with no stack trace), else its message. Where the documentation stops: Sentry
|
|
34
|
+
* groups by its grouping configuration (https://docs.sentry.io/concepts/data-management/event-grouping/), whose
|
|
35
|
+
* algorithm is not reproduced; this keeps its rule's shape: the stack trace first, then the exception, then the message. */
|
|
36
|
+
export declare function groupingHash(ctx: Pick<HandlerContext, 'crypto'>, payload: Row): string;
|
|
37
|
+
/** An event's tags as the API lists them: the SDK's own, and the ones Sentry derives from the event. */
|
|
38
|
+
export declare function tagsOf(payload: Row): Array<{
|
|
39
|
+
key: string;
|
|
40
|
+
value: string;
|
|
41
|
+
}>;
|
|
42
|
+
/** An error or message event kept, grouped into its issue (made, or counted again). */
|
|
43
|
+
export declare function keepEvent(ctx: HandlerContext, project: Row, payload: Row, type: string): Promise<Row>;
|
|
44
|
+
/** An event as a project's event list answers it (the spec's listProjectEvents item). */
|
|
45
|
+
export declare function simpleEvent(e: Row): Row;
|
|
46
|
+
/** An event in full (the spec's getProjectEvent): the simple fields, its entries (the exception with its stack
|
|
47
|
+
* traces, the breadcrumbs, the request, the message), its contexts, SDK, release and neighbours. */
|
|
48
|
+
export declare function fullEvent(ctx: Reader, raw: Row): Row;
|
|
49
|
+
/** An issue as the API answers it (the spec's issue schema, its common fields). */
|
|
50
|
+
export declare function issueView(ctx: Reader, raw: Row): Row;
|
|
51
|
+
/** Stored vendor fields, including the API's own _meta; private association/payload fields stay in the tree. */
|
|
52
|
+
export declare function wire(ctx: Reader, row: Row): Row;
|
|
53
|
+
export declare const ORG = "organization";
|
|
54
|
+
export declare const PROJECT = "project";
|
|
55
|
+
export declare const CLIENT_KEY = "project_key";
|
|
56
|
+
export declare const TOKEN = "_auth_token";
|
|
57
|
+
/** An id in Sentry's form: a number, as a string. Where the documentation stops: how Sentry mints its ids is not
|
|
58
|
+
* published; ctx.mint makes hash-derived decimal ids at the declared width, the same every run. */
|
|
59
|
+
export declare const orgBySlug: (ctx: Reader, ref: string) => Row | undefined;
|
|
60
|
+
export declare const projectOf: (ctx: Reader, org: Row, ref: string) => Row | undefined;
|
|
61
|
+
export declare const projectById: (ctx: Reader, id: string) => Row | undefined;
|
|
62
|
+
/** The host a DSN names for an organization. */
|
|
63
|
+
export declare const ingestHost: (org: Row) => string;
|
|
64
|
+
/** A project's DSN, from its client key. */
|
|
65
|
+
export declare const dsnOf: (org: Row, project: Row, key: Row) => string;
|
|
66
|
+
/** A project's active client key. */
|
|
67
|
+
export declare const keyOf: (ctx: Reader, project: Row) => Row | undefined;
|
|
68
|
+
/** The project a DSN's public key belongs to. */
|
|
69
|
+
export declare const projectByKey: (ctx: Reader, publicKey: string) => Row | undefined;
|
|
70
|
+
/** The World's next number in a sequence (a project's id, a nonce): issued from the tree over the lane's declared
|
|
71
|
+
* `_seq_<what>` (ctx.issue), never a row count. */
|
|
72
|
+
export declare const next: (ctx: Pick<HandlerContext, "issue">, what: string) => Promise<number>;
|
|
73
|
+
export declare const EVENT = "event";
|
|
74
|
+
export declare const ISSUE = "issue";
|
|
75
|
+
/** One user an issue's events came from (its `userCount` counts them): bookkeeping the vendor serves only as the count. */
|
|
76
|
+
export declare const ISSUE_USER = "_issue_user";
|
|
77
|
+
export declare const SESSION = "_session";
|
|
78
|
+
export declare const CLIENT_REPORT = "_client_report";
|
|
79
|
+
export declare const ATTACHMENT = "_attachment";
|
|
80
|
+
export declare const REPLAY = "_replay";
|
|
81
|
+
export declare const PROFILE = "_profile";
|
|
82
|
+
export declare const MONITOR = "monitor";
|
|
83
|
+
export declare const CHECK_IN = "check_in";
|
|
84
|
+
export declare const LOG = "_log";
|
|
85
|
+
export declare const METRIC = "_metric";
|
|
86
|
+
export declare const OTHER_ITEM = "_envelope_item";
|
|
87
|
+
export {};
|