The reason each better-supabase block column that CentraKit maps to null stays unmapped.
better-supabase.config.ts maps some block columns to null, so the block skips the feature that needs them. This page gives the reason for each one. Map a column when CentraKit adds the feature, and remove its line here.
Run the list again with a script that walks blocks.*.columns in the config and prints every null leaf.
log.actorRole: audit rows record the actor kind and id; the role is read from PermDock when needed, not stored per row.log.new, log.old: CentraKit stores only changed_columns and redacted safe_metadata, never full row images, so audit rows hold no personal data.log.op: the operation is part of event_type (<prefix>.created, .updated, .deleted).log.table: target_type names the table, so a second column would repeat it.restricted.new, restricted.old: restricted entries keep the same no-row-image rule as the main log.alarms.at, alarms.description, alarms.related, alarms.repeat, alarms.repeatMinutes, alarms.summary, alarms.user: agenda reminders are only an offset and a method per item; absolute, repeating and per-user alarms are not a product feature.attendees.subjectId, attendees.subjectType: attendees link to users, customers and customer contacts through their own columns, not a generic subject.calendars.ownerType: every agenda collection is owned by a user (owner_user_id); team and organization calendars do not exist.events.autoDecline: CentraKit does not auto-decline invitations on busy calendars.events.color: an item takes the color of its collection; items have no color of their own.events.exdates, events.rdates, events.rrule: recurrence lives in agenda_item_recurrence_rules and in detached instances (recurrence_id_at), which the rules mapping covers.events.kind: source (item, google-calendar) is the only kind distinction CentraKit has.events.subjectId, events.subjectType: an item links to a task through task_id, and hiring links interviews from hiring_interviews.agenda_item_id, so items carry no generic subject.rules.byMonth, rules.bySetPos: the recurrence editor offers no yearly-by-month or set-position rules.rules.id: the rule table is keyed by agenda_item_id, one rule per item.rules.rrule: rules are stored as structured columns, not as an RRULE string.variants.trackInventory: stock tracking is set on the product (products.track_inventory), not per variant.values.definition, values.optionId, values.valueEmail, values.valueJson: asset custom attributes are a keyed layout with the label and type on each value row; there are no shared definitions, options, email or JSON values.values.rank: values are ordered by position, which the keyed layout maps.values.subjectId, values.subjectType: a value belongs to a product or a customer asset through product_id and customer_asset_id, not a generic subject.driveGrants.principalId, driveGrants.principalType, grants.principalId, grants.principalType: grants name a user or a team in their own columns (user_id, team_id), which the block maps instead.nodes.attachment: a drive file keeps its content in file versions (current_version_id), not in the attachments block.nodes.path: folder paths are resolved from parent_id; no materialized path is stored.nodes.rank: drive listings sort by name and type, with no manual order.contracts.salaryPeriod: the pay period is pay_frequency, which fields writes with the other pay columns.employees.name: CentraKit stores first_name and last_name and builds the display name when it reads.privateDetails.address, privateDetails.addressLine2, privateDetails.region: the home address is four flat columns (line 1, postal code, city, country), which privateDetailsInput fills.privateDetails.emergencyContacts: there is one emergency contact in three flat columns, not a list.privateDetails.nationalId: CentraKit does not collect national identity numbers.privateDetails.updatedBy, privateDetails.user: private details are keyed by employee_id; the audit trigger records who changed them.categories.currency, categories.limitAmount, categories.receiptOver: spending limits and receipt thresholds live in expense_policies, not on the category.categories.key: categories are tenant data identified by id; there are no system category keys.expenses.approvedAt, expenses.rejectedAt: a decision is decided_at and decided_by with the outcome in status.expenses.createdBy: the track_actor trigger fills created_by, so the block must not write it.expenses.user: an expense belongs to an employee (employee_id), and the employees block resolves the user.applications.candidateType: every candidate is a hiring_candidates row, so there is one candidate type.applications.owner: ownership sits on the job (hiring manager), not on each application.applications.pipeline: an application follows the stages of its job; there are no separate pipelines.interviews.interviewers: interviewers live in hiring_interview_interviewers, one row each.interviews.kind: interviews have no type; the agenda item carries the location or meeting link.scorecardScores.notes: notes are kept on the scorecard, not per criterion.scorecards.recommendation: the overall rating is the recommendation.invitations.acceptedBy, platformInvitations.acceptedBy: acceptance creates the membership, which records the user; the invitation keeps only accepted_at.balances.key, balances.user: balances are rows of time_off_ledger keyed by employee and type, through the app balances table.requests.approval: time-off approvals go through CentraKit's approvals module (supabase-people/src/approvals.ts), not a block approval column.requests.cancelledBy: the audit trigger records who canceled; the request keeps canceled_at.requests.partial: partial days are start_part, end_part and hours, which the block maps separately.requests.user: a request belongs to an employee (employee_id).types.allowance, types.carryoverMax: entitlements come from time_off_policies, not from the type.types.autoApprove: the type has requires_approval, the inverse, which the app checks.types.key: leave types are tenant data identified by id.deliveries.attempts, deliveries.nextAttemptAt: notification_deliveries has no retry columns, so the block keeps one attempt (attempted_at) and its outcome per row.deliveries.providerStatus, deliveries.providerStatusAt: the row keeps the mapped status and delivered_at, not the raw provider status.deliveries.templateKey: the template follows from the event type.events.key: notification events are not deduplicated by key.preferences.updatedAt, subscriptions.updatedAt: these rows are replaced, not edited, so created_at is enough.organizations.createdBy: the first owner membership records who created the organization.organizations.deletedAt: deletion runs through the data-lifecycle block's deletion requests and purge, with disabled_at for suspension.events.subject: public.workflow_events has no subject column; consumers read the subject from the payload.profiles.avatar: the avatar is avatar_path in Storage, served through the storage helpers, not a URL column the block can fill.profiles.fullName: CentraKit stores first_name and last_name.profiles.onboarding: CentraKit keeps no onboarding checklist state on the profile.tags.rank: tags are ordered by position.items.estimate: quoted hours come from quote lines (task_quoted_hours), not a task column.items.iteration, items.project: CentraKit has no sprints or projects; tasks group by customer, team and pipeline.items.progress: tasks have no progress percentage; the pipeline stage and the subtasks show how far a task is.items.recursFrom: recurring work is created from task templates, not by cloning a task.entries.endedAt: an entry is started_at plus duration_seconds.entries.subjectId, entries.subjectType: an entry links to a task, a customer or an agenda item through its own columns.timesheets.approval: timesheet decisions are decided_at, decided_by and status.timesheets.user: a timesheet belongs to an employee (employee_id).Last updated on