feat(backend): register 8 Smart Actions feature flags with route gating
This commit is contained in:
parent
c71b01681f
commit
1b4b5af995
@ -17,6 +17,13 @@ const registry = createFlagRegistry({
|
|||||||
'notelett_auto_embed_enabled': false,
|
'notelett_auto_embed_enabled': false,
|
||||||
'notelett_duplicate_check_enabled': true,
|
'notelett_duplicate_check_enabled': true,
|
||||||
'notelett_suggest_links_enabled': true,
|
'notelett_suggest_links_enabled': true,
|
||||||
|
// Smart Actions feature flags (§6.3)
|
||||||
|
'notelett_smart_actions_enabled': false,
|
||||||
|
'notelett_auto_link_enabled': false,
|
||||||
|
'notelett_copilot_llm_enabled': false,
|
||||||
|
'notelett_voice_capture_enabled': false,
|
||||||
|
'notelett_scheduled_actions_enabled': false,
|
||||||
|
'notelett_webhooks_enabled': false,
|
||||||
},
|
},
|
||||||
enabled: config.FEATURE_FLAGS_ENABLED,
|
enabled: config.FEATURE_FLAGS_ENABLED,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import type { FastifyInstance } from 'fastify';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { getUserId, getRequestProductId } from '../../lib/request-context.js';
|
import { getUserId, getRequestProductId } from '../../lib/request-context.js';
|
||||||
import { BadRequestError, NotFoundError } from '@bytelyst/errors';
|
import { BadRequestError, NotFoundError } from '@bytelyst/errors';
|
||||||
|
import { isFeatureEnabled } from '../../lib/feature-flags.js';
|
||||||
import { embedText, cosineSimilarity, stripHtmlForEmbedding } from '../../lib/embeddings.js';
|
import { embedText, cosineSimilarity, stripHtmlForEmbedding } from '../../lib/embeddings.js';
|
||||||
import { llm } from '../../lib/llm.js';
|
import { llm } from '../../lib/llm.js';
|
||||||
import {
|
import {
|
||||||
@ -70,6 +71,7 @@ export async function notePromptRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
|
|
||||||
// ── Run a prompt template against a note ────────────────────────
|
// ── Run a prompt template against a note ────────────────────────
|
||||||
app.post('/note-prompts/run', async (req) => {
|
app.post('/note-prompts/run', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_smart_actions_enabled')) throw new BadRequestError('Smart Actions are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const productId = getRequestProductId(req);
|
const productId = getRequestProductId(req);
|
||||||
const input = RunPromptSchema.parse(req.body);
|
const input = RunPromptSchema.parse(req.body);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { getUserId, getRequestProductId } from '../../lib/request-context.js';
|
|||||||
import { BadRequestError, NotFoundError } from '@bytelyst/errors';
|
import { BadRequestError, NotFoundError } from '@bytelyst/errors';
|
||||||
import { getCollection } from '../../lib/datastore.js';
|
import { getCollection } from '../../lib/datastore.js';
|
||||||
import { PRODUCT_ID } from '../../lib/product-config.js';
|
import { PRODUCT_ID } from '../../lib/product-config.js';
|
||||||
|
import { isFeatureEnabled } from '../../lib/feature-flags.js';
|
||||||
import { llm } from '../../lib/llm.js';
|
import { llm } from '../../lib/llm.js';
|
||||||
import * as noteRepo from '../notes/repository.js';
|
import * as noteRepo from '../notes/repository.js';
|
||||||
import * as promptRepo from './repository.js';
|
import * as promptRepo from './repository.js';
|
||||||
@ -241,6 +242,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
// ── Schedule CRUD ─────────────────────────────────────────────
|
// ── Schedule CRUD ─────────────────────────────────────────────
|
||||||
|
|
||||||
app.get('/prompt-schedules', async (req) => {
|
app.get('/prompt-schedules', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_scheduled_actions_enabled')) throw new BadRequestError('Scheduled actions are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const items = await scheduleCollection().findMany({
|
const items = await scheduleCollection().findMany({
|
||||||
filter: { productId: PRODUCT_ID, userId },
|
filter: { productId: PRODUCT_ID, userId },
|
||||||
@ -251,6 +253,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post('/prompt-schedules', async (req, reply) => {
|
app.post('/prompt-schedules', async (req, reply) => {
|
||||||
|
if (!isFeatureEnabled('notelett_scheduled_actions_enabled')) throw new BadRequestError('Scheduled actions are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const input = CreateScheduleSchema.parse(req.body);
|
const input = CreateScheduleSchema.parse(req.body);
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
@ -274,6 +277,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get('/prompt-schedules/:id', async (req) => {
|
app.get('/prompt-schedules/:id', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_scheduled_actions_enabled')) throw new BadRequestError('Scheduled actions are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const doc = await scheduleCollection().findById(id, userId);
|
const doc = await scheduleCollection().findById(id, userId);
|
||||||
@ -282,6 +286,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.patch('/prompt-schedules/:id', async (req) => {
|
app.patch('/prompt-schedules/:id', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_scheduled_actions_enabled')) throw new BadRequestError('Scheduled actions are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const input = UpdateScheduleSchema.parse(req.body);
|
const input = UpdateScheduleSchema.parse(req.body);
|
||||||
@ -298,6 +303,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.delete('/prompt-schedules/:id', async (req, reply) => {
|
app.delete('/prompt-schedules/:id', async (req, reply) => {
|
||||||
|
if (!isFeatureEnabled('notelett_scheduled_actions_enabled')) throw new BadRequestError('Scheduled actions are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const existing = await scheduleCollection().findById(id, userId);
|
const existing = await scheduleCollection().findById(id, userId);
|
||||||
@ -309,6 +315,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
// ── Webhook CRUD ──────────────────────────────────────────────
|
// ── Webhook CRUD ──────────────────────────────────────────────
|
||||||
|
|
||||||
app.get('/prompt-webhooks', async (req) => {
|
app.get('/prompt-webhooks', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_webhooks_enabled')) throw new BadRequestError('Webhooks are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const items = await webhookCollection().findMany({
|
const items = await webhookCollection().findMany({
|
||||||
filter: { productId: PRODUCT_ID, userId },
|
filter: { productId: PRODUCT_ID, userId },
|
||||||
@ -319,6 +326,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post('/prompt-webhooks', async (req, reply) => {
|
app.post('/prompt-webhooks', async (req, reply) => {
|
||||||
|
if (!isFeatureEnabled('notelett_webhooks_enabled')) throw new BadRequestError('Webhooks are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const input = CreateWebhookSchema.parse(req.body);
|
const input = CreateWebhookSchema.parse(req.body);
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
@ -342,6 +350,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get('/prompt-webhooks/:id', async (req) => {
|
app.get('/prompt-webhooks/:id', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_webhooks_enabled')) throw new BadRequestError('Webhooks are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const doc = await webhookCollection().findById(id, userId);
|
const doc = await webhookCollection().findById(id, userId);
|
||||||
@ -350,6 +359,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.patch('/prompt-webhooks/:id', async (req) => {
|
app.patch('/prompt-webhooks/:id', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_webhooks_enabled')) throw new BadRequestError('Webhooks are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const input = UpdateWebhookSchema.parse(req.body);
|
const input = UpdateWebhookSchema.parse(req.body);
|
||||||
@ -361,6 +371,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.delete('/prompt-webhooks/:id', async (req, reply) => {
|
app.delete('/prompt-webhooks/:id', async (req, reply) => {
|
||||||
|
if (!isFeatureEnabled('notelett_webhooks_enabled')) throw new BadRequestError('Webhooks are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const existing = await webhookCollection().findById(id, userId);
|
const existing = await webhookCollection().findById(id, userId);
|
||||||
@ -372,6 +383,7 @@ export async function promptSchedulerRoutes(app: FastifyInstance): Promise<void>
|
|||||||
// ── Trigger a webhook (F26) ───────────────────────────────────
|
// ── Trigger a webhook (F26) ───────────────────────────────────
|
||||||
|
|
||||||
app.post('/prompt-webhooks/:id/trigger', async (req) => {
|
app.post('/prompt-webhooks/:id/trigger', async (req) => {
|
||||||
|
if (!isFeatureEnabled('notelett_webhooks_enabled')) throw new BadRequestError('Webhooks are disabled');
|
||||||
const userId = getUserId(req);
|
const userId = getUserId(req);
|
||||||
const { id } = req.params as { id: string };
|
const { id } = req.params as { id: string };
|
||||||
const input = TriggerWebhookSchema.parse(req.body);
|
const input = TriggerWebhookSchema.parse(req.body);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user