Infrastructure build to support third-party app integrations
This commit is contained in:
55
backend/types/domain.ts
Normal file
55
backend/types/domain.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
export type Note = {
|
||||
id: string;
|
||||
text: string;
|
||||
x: number;
|
||||
y: number;
|
||||
author: string;
|
||||
color: string;
|
||||
};
|
||||
|
||||
/** Shape accepted when writing a note; positional and color fields fall back to defaults. */
|
||||
export type NoteInput = {
|
||||
id: string;
|
||||
text: string;
|
||||
author: string;
|
||||
x?: number;
|
||||
y?: number;
|
||||
color?: string;
|
||||
sourceMeta?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type Cluster = {
|
||||
label: string;
|
||||
noteIds: string[];
|
||||
};
|
||||
|
||||
export type ClusterResponse = {
|
||||
clusters: Cluster[];
|
||||
score: number;
|
||||
};
|
||||
|
||||
export type ValidationResult = {
|
||||
valid: boolean;
|
||||
reasons: string[];
|
||||
};
|
||||
|
||||
/** noteId to embedding vector. */
|
||||
export type EmbeddingMap = Map<string, number[]>;
|
||||
|
||||
const isStringArray = (value: unknown): value is string[] =>
|
||||
Array.isArray(value) && value.every((entry) => typeof entry === 'string');
|
||||
|
||||
/**
|
||||
* Runtime guard for LLM output, which arrives as parsed JSON of unknown shape.
|
||||
* Structural correctness beyond this (complete coverage, no duplicates) is the
|
||||
* job of validateStructure.
|
||||
*/
|
||||
export const isClusterArray = (value: unknown): value is Cluster[] => {
|
||||
if (!Array.isArray(value)) return false;
|
||||
|
||||
return value.every((entry) => {
|
||||
if (typeof entry !== 'object' || entry === null) return false;
|
||||
const candidate = entry as Record<string, unknown>;
|
||||
return typeof candidate.label === 'string' && isStringArray(candidate.noteIds);
|
||||
});
|
||||
};
|
||||
43
backend/types/integration.ts
Normal file
43
backend/types/integration.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { NoteInput } from './domain.js';
|
||||
|
||||
export type ProviderSlug = 'slack' | 'jira' | 'linear' | 'github' | 'rest';
|
||||
|
||||
export type SignatureScheme = 'slack-v0' | 'github-sha256' | 'linear-sha256' | 'none';
|
||||
|
||||
export type DeliveryStatus = 'pending' | 'processing' | 'done' | 'failed';
|
||||
|
||||
/**
|
||||
* Integration as exposed to application code. Ciphertext columns are
|
||||
* deliberately absent so a value of this type can never leak a secret.
|
||||
*/
|
||||
export type IntegrationRow = {
|
||||
id: number;
|
||||
provider: ProviderSlug;
|
||||
externalWorkspaceId: string | null;
|
||||
displayName: string | null;
|
||||
scopes: string[];
|
||||
tokenExpiresAt: Date | null;
|
||||
};
|
||||
|
||||
export type SignatureResult =
|
||||
| { ok: true }
|
||||
| { ok: false; reason: 'missing' | 'malformed' | 'mismatch' | 'stale' };
|
||||
|
||||
export type NormalizedDelivery = {
|
||||
externalId: string;
|
||||
notes: NoteInput[];
|
||||
};
|
||||
|
||||
/** Provenance recorded on each ingested note's source_meta column. */
|
||||
export type NoteProvenance = {
|
||||
provider: ProviderSlug;
|
||||
externalId: string;
|
||||
permalink?: string;
|
||||
authorHandle?: string;
|
||||
receivedAt: string;
|
||||
};
|
||||
|
||||
const SLUGS: readonly string[] = ['slack', 'jira', 'linear', 'github', 'rest'];
|
||||
|
||||
export const isProviderSlug = (value: string): value is ProviderSlug =>
|
||||
SLUGS.includes(value);
|
||||
Reference in New Issue
Block a user