Beyond find, a content type may offer two more:
'documents' => function (): \Generator {
foreach ($rows as $row) {
yield new Document(
type: 'example', id: (int) $row['id'],
title: $row['title'], url: '/examples/' . $row['slug'],
gate: 'category:' . $row['category_id'],
);
}
},
'gates' => fn (array $groupIds): array =>
array_map(fn (int $id) => 'category:' . $id, $readableCategoryIds),🚨 Never put a permission in a document. The gate is the container, and who may read that container is resolved at query time against the database. Storing group ids instead would mean restricting a container leaves every document in it stale — still saying everybody may see them — until a reindex catches up.
🚨 Provide both callbacks or neither. A type with documents and no gates is skipped entirely rather than indexed as public. Forgetting has to produce absence, which somebody notices, rather than disclosure, which nobody does.
A generator, not an array — a real community has hundreds of thousands of rows.