feat(meeting-intelligence): add conference_prefix filter for space-scoped meetings

Adds optional conference_prefix query param to GET /meetings that filters
by conference_id LIKE prefix%. This enables rMeets to scope MI data per space.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-04-10 18:37:25 -04:00
parent 2984a2944c
commit 1706dc47a3
2 changed files with 61 additions and 43 deletions

View File

@ -48,29 +48,37 @@ class Database:
self,
limit: int = 50,
offset: int = 0,
status: Optional[str] = None
status: Optional[str] = None,
conference_prefix: Optional[str] = None
) -> List[Dict[str, Any]]:
"""List meetings with pagination."""
"""List meetings with pagination. Optionally filter by conference_id prefix."""
async with self.pool.acquire() as conn:
conditions = []
params: list = []
idx = 1
if status:
rows = await conn.fetch("""
conditions.append(f"status = ${idx}")
params.append(status)
idx += 1
if conference_prefix:
conditions.append(f"conference_id LIKE ${idx}")
params.append(conference_prefix + "%")
idx += 1
where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
params.extend([limit, offset])
rows = await conn.fetch(f"""
SELECT id, conference_id, conference_name, title,
started_at, ended_at, duration_seconds,
status, created_at
FROM meetings
WHERE status = $1
{where}
ORDER BY created_at DESC
LIMIT $2 OFFSET $3
""", status, limit, offset)
else:
rows = await conn.fetch("""
SELECT id, conference_id, conference_name, title,
started_at, ended_at, duration_seconds,
status, created_at
FROM meetings
ORDER BY created_at DESC
LIMIT $1 OFFSET $2
""", limit, offset)
LIMIT ${idx} OFFSET ${idx + 1}
""", *params)
return [dict(row) for row in rows]
@ -156,33 +164,40 @@ class Database:
tokens: List[str],
limit: int = 50,
offset: int = 0,
status: Optional[str] = None
status: Optional[str] = None,
conference_prefix: Optional[str] = None
) -> List[Dict[str, Any]]:
"""List meetings filtered by access tokens."""
"""List meetings filtered by access tokens. Optionally filter by conference_id prefix."""
if not tokens:
return []
async with self.pool.acquire() as conn:
conditions = ["access_token = ANY($1)"]
params: list = [tokens]
idx = 2
if status:
rows = await conn.fetch("""
conditions.append(f"status = ${idx}")
params.append(status)
idx += 1
if conference_prefix:
conditions.append(f"conference_id LIKE ${idx}")
params.append(conference_prefix + "%")
idx += 1
where = " AND ".join(conditions)
params.extend([limit, offset])
rows = await conn.fetch(f"""
SELECT id, conference_id, conference_name, title,
started_at, ended_at, duration_seconds,
status, created_at
FROM meetings
WHERE access_token = ANY($1) AND status = $2
WHERE {where}
ORDER BY created_at DESC
LIMIT $3 OFFSET $4
""", tokens, status, limit, offset)
else:
rows = await conn.fetch("""
SELECT id, conference_id, conference_name, title,
started_at, ended_at, duration_seconds,
status, created_at
FROM meetings
WHERE access_token = ANY($1)
ORDER BY created_at DESC
LIMIT $2 OFFSET $3
""", tokens, limit, offset)
LIMIT ${idx} OFFSET ${idx + 1}
""", *params)
return [dict(row) for row in rows]

View File

@ -76,12 +76,14 @@ async def list_meetings(
request: Request,
limit: int = Query(default=50, le=100),
offset: int = Query(default=0, ge=0),
status: Optional[str] = Query(default=None)
status: Optional[str] = Query(default=None),
conference_prefix: Optional[str] = Query(default=None, description="Filter by conference_id prefix (e.g. space slug)")
):
"""List meetings the caller has access to.
Requires X-MI-Tokens header with comma-separated access tokens.
Returns only meetings matching the provided tokens.
Optionally filter by conference_prefix to scope to a space.
"""
db = request.app.state.db
tokens = get_multi_tokens(request)
@ -90,7 +92,8 @@ async def list_meetings(
return MeetingListResponse(meetings=[], total=0, limit=limit, offset=offset)
meetings = await db.list_meetings_by_tokens(
tokens=tokens, limit=limit, offset=offset, status=status
tokens=tokens, limit=limit, offset=offset, status=status,
conference_prefix=conference_prefix
)
return MeetingListResponse(