@vellumai/assistant 0.3.23 → 0.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -84
  3. package/src/__tests__/approval-primitive.test.ts +72 -0
  4. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -4
  5. package/src/__tests__/ipc-snapshot.test.ts +0 -42
  6. package/src/__tests__/skill-feature-flags-integration.test.ts +0 -4
  7. package/src/__tests__/tool-approval-handler.test.ts +94 -5
  8. package/src/cli/mcp.ts +20 -0
  9. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +13 -8
  10. package/src/config/bundled-skills/reminder/SKILL.md +7 -6
  11. package/src/config/bundled-skills/reminder/TOOLS.json +1 -1
  12. package/src/config/bundled-skills/time-based-actions/SKILL.md +7 -6
  13. package/src/config/system-prompt.ts +0 -72
  14. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +14 -6
  15. package/src/daemon/handlers/config.ts +0 -4
  16. package/src/daemon/handlers/navigate-settings.ts +0 -1
  17. package/src/daemon/ipc-contract-inventory.json +0 -10
  18. package/src/daemon/ipc-contract.ts +0 -4
  19. package/src/daemon/session-process.ts +2 -2
  20. package/src/permissions/checker.ts +4 -4
  21. package/src/runtime/routes/inbound-message-handler.ts +2 -2
  22. package/src/runtime/routes/ingress-routes.ts +7 -2
  23. package/src/tools/executor.ts +2 -2
  24. package/src/tools/reminder/reminder-store.ts +1 -1
  25. package/src/tools/reminder/reminder.ts +1 -1
  26. package/src/tools/system/navigate-settings.ts +0 -1
  27. package/src/tools/tool-approval-handler.ts +2 -33
  28. package/src/daemon/handlers/config-parental.ts +0 -164
  29. package/src/daemon/ipc-contract/parental-control.ts +0 -109
  30. package/src/security/parental-control-store.ts +0 -184
@@ -14,7 +14,6 @@
14
14
  * config-twilio.ts — Twilio SMS/voice configuration
15
15
  * config-channels.ts — Channel guardian & readiness
16
16
  * config-tools.ts — Env vars, tool permission simulation, tool names
17
- * config-parental.ts — Parental control PIN + content/tool restrictions
18
17
  */
19
18
 
20
19
  // Re-export individual handlers for direct import by tests and other modules
@@ -23,7 +22,6 @@ export { handleHeartbeatChecklistRead, handleHeartbeatChecklistWrite,handleHeart
23
22
  export { computeGatewayTarget, handleIngressConfig, syncTwilioWebhooks,triggerGatewayReconcile } from './config-ingress.js';
24
23
  export { handleTwitterIntegrationConfig,handleVercelApiConfig } from './config-integrations.js';
25
24
  export { handleImageGenModelSet,handleModelGet, handleModelSet } from './config-model.js';
26
- export { handleParentalControlGet, handleParentalControlSetPin, handleParentalControlUpdate,handleParentalControlVerifyPin } from './config-parental.js';
27
25
  export { handlePlatformConfig } from './config-platform.js';
28
26
  export { handleReminderCancel,handleRemindersList, handleScheduleRemove, handleScheduleRunNow, handleSchedulesList, handleScheduleToggle } from './config-scheduling.js';
29
27
  export { handleShareToSlack, handleSlackWebhookConfig } from './config-slack.js';
@@ -39,7 +37,6 @@ import { heartbeatHandlers } from './config-heartbeat.js';
39
37
  import { ingressHandlers } from './config-ingress.js';
40
38
  import { integrationHandlers } from './config-integrations.js';
41
39
  import { modelHandlers } from './config-model.js';
42
- import { parentalControlHandlers } from './config-parental.js';
43
40
  import { platformHandlers } from './config-platform.js';
44
41
  import { schedulingHandlers } from './config-scheduling.js';
45
42
  import { slackHandlers } from './config-slack.js';
@@ -61,7 +58,6 @@ export const configHandlers = {
61
58
  ...twilioHandlers,
62
59
  ...channelHandlers,
63
60
  ...toolHandlers,
64
- ...parentalControlHandlers,
65
61
  ...heartbeatHandlers,
66
62
  ...voiceHandlers,
67
63
  };
@@ -13,7 +13,6 @@ export const SETTINGS_TABS = [
13
13
  'Wake Word',
14
14
  'Appearance',
15
15
  'Advanced',
16
- 'Parental',
17
16
  ] as const;
18
17
 
19
18
  export type SettingsTabId = (typeof SETTINGS_TABS)[number];
@@ -11,7 +11,6 @@
11
11
  "_MessagesClientMessages",
12
12
  "_NotificationsClientMessages",
13
13
  "_PairingClientMessages",
14
- "_ParentalControlClientMessages",
15
14
  "_SchedulesClientMessages",
16
15
  "_SessionsClientMessages",
17
16
  "_SettingsClientMessages",
@@ -36,7 +35,6 @@
36
35
  "_MessagesServerMessages",
37
36
  "_NotificationsServerMessages",
38
37
  "_PairingServerMessages",
39
- "_ParentalControlServerMessages",
40
38
  "_SchedulesServerMessages",
41
39
  "_SessionsServerMessages",
42
40
  "_SettingsServerMessages",
@@ -117,10 +115,6 @@
117
115
  "oauth_connect_start",
118
116
  "open_bundle",
119
117
  "pairing_approval_response",
120
- "parental_control_get",
121
- "parental_control_set_pin",
122
- "parental_control_update",
123
- "parental_control_verify_pin",
124
118
  "ping",
125
119
  "platform_config",
126
120
  "publish_page",
@@ -281,10 +275,6 @@
281
275
  "open_bundle_response",
282
276
  "open_url",
283
277
  "pairing_approval_request",
284
- "parental_control_get_response",
285
- "parental_control_set_pin_response",
286
- "parental_control_update_response",
287
- "parental_control_verify_pin_response",
288
278
  "platform_config_response",
289
279
  "pong",
290
280
  "publish_page_response",
@@ -25,7 +25,6 @@ export * from './ipc-contract/memory.js';
25
25
  export * from './ipc-contract/messages.js';
26
26
  export * from './ipc-contract/notifications.js';
27
27
  export * from './ipc-contract/pairing.js';
28
- export * from './ipc-contract/parental-control.js';
29
28
  export * from './ipc-contract/schedules.js';
30
29
  export * from './ipc-contract/sessions.js';
31
30
  export * from './ipc-contract/settings.js';
@@ -50,7 +49,6 @@ import type { _MemoryServerMessages } from './ipc-contract/memory.js';
50
49
  import type { _MessagesClientMessages, _MessagesServerMessages } from './ipc-contract/messages.js';
51
50
  import type { _NotificationsClientMessages, _NotificationsServerMessages } from './ipc-contract/notifications.js';
52
51
  import type { _PairingClientMessages, _PairingServerMessages } from './ipc-contract/pairing.js';
53
- import type { _ParentalControlClientMessages, _ParentalControlServerMessages } from './ipc-contract/parental-control.js';
54
52
  import type { _SchedulesClientMessages, _SchedulesServerMessages } from './ipc-contract/schedules.js';
55
53
  import type { _SessionsClientMessages, _SessionsServerMessages } from './ipc-contract/sessions.js';
56
54
  import type { _SettingsClientMessages, _SettingsServerMessages } from './ipc-contract/settings.js';
@@ -89,7 +87,6 @@ export type ClientMessage =
89
87
  | _WorkspaceClientMessages
90
88
  | _SchedulesClientMessages
91
89
  | _DiagnosticsClientMessages
92
- | _ParentalControlClientMessages
93
90
  | _InboxClientMessages
94
91
  | _PairingClientMessages
95
92
  | _NotificationsClientMessages
@@ -116,7 +113,6 @@ export type ServerMessage =
116
113
  | _SchedulesServerMessages
117
114
  | _SettingsServerMessages
118
115
  | _DiagnosticsServerMessages
119
- | _ParentalControlServerMessages
120
116
  | _InboxServerMessages
121
117
  | _PairingServerMessages
122
118
  | _NotificationsServerMessages
@@ -576,9 +576,9 @@ export async function processMessage(
576
576
 
577
577
  let stateApplied = true;
578
578
  if (turnResult.disposition === 'call_back' || turnResult.disposition === 'message_back') {
579
- stateApplied = progressFollowupState(request.id, 'dispatching', turnResult.disposition) !== undefined;
579
+ stateApplied = progressFollowupState(request.id, 'dispatching', turnResult.disposition) !== null;
580
580
  } else if (turnResult.disposition === 'decline') {
581
- stateApplied = finalizeFollowup(request.id, 'declined') !== undefined;
581
+ stateApplied = finalizeFollowup(request.id, 'declined') !== null;
582
582
  }
583
583
 
584
584
  if (!stateApplied) {
@@ -398,10 +398,10 @@ async function classifyRiskUncached(toolName: string, input: Record<string, unkn
398
398
  if (HIGH_RISK_PROGRAMS.has(prog)) return RiskLevel.High;
399
399
 
400
400
  if (prog === 'rm') {
401
- // `rm` of known safe workspace files (no flags, bare filename) is
402
- // Medium rather than High so scope-limited allow rules can approve
403
- // it without needing allowHighRisk, which would bypass path checks.
404
- if (isRmOfKnownSafeFile(seg.args)) {
401
+ // Only downgrade rm of known safe workspace files for sandboxed bash.
402
+ // host_bash has a global allow rule that would auto-approve Medium-risk
403
+ // commands, so rm on the host must always require explicit approval.
404
+ if (toolName === 'bash' && isRmOfKnownSafeFile(seg.args)) {
405
405
  maxRisk = RiskLevel.Medium;
406
406
  continue;
407
407
  }
@@ -1087,9 +1087,9 @@ export async function handleChannelInbound(
1087
1087
 
1088
1088
  let stateApplied = true;
1089
1089
  if (turnResult.disposition === 'call_back' || turnResult.disposition === 'message_back') {
1090
- stateApplied = progressFollowupState(request.id, 'dispatching', turnResult.disposition) !== undefined;
1090
+ stateApplied = progressFollowupState(request.id, 'dispatching', turnResult.disposition) !== null;
1091
1091
  } else if (turnResult.disposition === 'decline') {
1092
- stateApplied = finalizeFollowup(request.id, 'declined') !== undefined;
1092
+ stateApplied = finalizeFollowup(request.id, 'declined') !== null;
1093
1093
  }
1094
1094
 
1095
1095
  if (!stateApplied) {
@@ -93,8 +93,13 @@ export async function handleRevokeMember(req: Request, memberId: string): Promis
93
93
  * POST /v1/ingress/members/:id/block
94
94
  */
95
95
  export async function handleBlockMember(req: Request, memberId: string): Promise<Response> {
96
- const body = (await req.json()) as Record<string, unknown>;
97
- const reason = body.reason as string | undefined;
96
+ let reason: string | undefined;
97
+ try {
98
+ const body = (await req.json()) as Record<string, unknown>;
99
+ reason = body.reason as string | undefined;
100
+ } catch {
101
+ // Body is optional — callers may omit it entirely
102
+ }
98
103
 
99
104
  const result = blockIngressMember(memberId, reason);
100
105
 
@@ -56,8 +56,8 @@ export class ToolExecutor {
56
56
  startedAtMs: startTime,
57
57
  });
58
58
 
59
- // Run pre-execution approval gates (abort, parental controls, guardian
60
- // policy, allowed-tool-set, task-run preflight, tool registry lookup).
59
+ // Run pre-execution approval gates (abort, guardian policy,
60
+ // allowed-tool-set, task-run preflight, tool registry lookup).
61
61
  const gateResult = await this.approvalHandler.checkPreExecutionGates(
62
62
  name, input, context, executionTarget, riskLevel, startTime,
63
63
  (event) => emitLifecycleEvent(context, event),
@@ -52,7 +52,7 @@ export function insertReminder(params: {
52
52
  const db = getDb();
53
53
  const id = uuid();
54
54
  const now = Date.now();
55
- const routingIntent = params.routingIntent ?? 'single_channel';
55
+ const routingIntent = params.routingIntent ?? 'all_channels';
56
56
  const routingHints = params.routingHints ?? {};
57
57
  const row = {
58
58
  id,
@@ -38,7 +38,7 @@ export function executeReminderCreate(input: Record<string, unknown>): ToolExecu
38
38
  }
39
39
 
40
40
  // Validate routing_intent if provided
41
- const routingIntent: RoutingIntent = (routingIntentRaw as RoutingIntent) ?? 'single_channel';
41
+ const routingIntent: RoutingIntent = (routingIntentRaw as RoutingIntent) ?? 'all_channels';
42
42
  if (routingIntentRaw !== undefined && !VALID_ROUTING_INTENTS.has(routingIntentRaw)) {
43
43
  return {
44
44
  content: `Error: routing_intent must be one of: single_channel, multi_channel, all_channels`,
@@ -8,7 +8,6 @@ const SETTINGS_TABS = [
8
8
  'Trust',
9
9
  'Model',
10
10
  'Scheduling',
11
- 'Parental',
12
11
  ] as const;
13
12
 
14
13
  type SettingsTab = (typeof SETTINGS_TABS)[number];
@@ -1,5 +1,4 @@
1
1
  import { consumeGrantForInvocation } from '../approvals/approval-primitive.js';
2
- import { isToolBlocked } from '../security/parental-control-store.js';
3
2
  import { computeToolApprovalDigest } from '../security/tool-approval-digest.js';
4
3
  import { getTaskRunRules } from '../tasks/ephemeral-permissions.js';
5
4
  import { getLogger } from '../util/logger.js';
@@ -40,8 +39,8 @@ export type PreExecutionGateResult =
40
39
  | { allowed: false; result: ToolExecutionResult };
41
40
 
42
41
  /**
43
- * Handles pre-execution approval gates: abort checks, parental controls,
44
- * guardian policy, allowed-tool-set gating, and task-run preflight checks.
42
+ * Handles pre-execution approval gates: abort checks, guardian policy,
43
+ * allowed-tool-set gating, and task-run preflight checks.
45
44
  * These run before the interactive permission prompt flow.
46
45
  */
47
46
  export class ToolApprovalHandler {
@@ -81,36 +80,6 @@ export class ToolApprovalHandler {
81
80
  return { allowed: false, result: { content: 'Cancelled', isError: true } };
82
81
  }
83
82
 
84
- // Reject tools blocked by parental control settings before any permission check.
85
- if (isToolBlocked(name)) {
86
- log.warn(
87
- {
88
- toolName: name,
89
- sessionId: context.sessionId,
90
- conversationId: context.conversationId,
91
- principal: context.principal,
92
- reason: 'blocked_by_parental_controls',
93
- },
94
- 'Parental control blocked tool invocation',
95
- );
96
- const durationMs = Date.now() - startTime;
97
- emitLifecycleEvent({
98
- type: 'permission_denied',
99
- toolName: name,
100
- executionTarget,
101
- input,
102
- workingDir: context.workingDir,
103
- sessionId: context.sessionId,
104
- conversationId: context.conversationId,
105
- requestId: context.requestId,
106
- riskLevel,
107
- decision: 'deny',
108
- reason: 'Blocked by parental control settings',
109
- durationMs,
110
- });
111
- return { allowed: false, result: { content: 'This tool is blocked by parental control settings.', isError: true } };
112
- }
113
-
114
83
  // Reject tool invocations targeting guardian control-plane endpoints from non-guardian actors.
115
84
  const guardianCheck = enforceGuardianOnlyPolicy(name, input, context.guardianActorRole);
116
85
  if (guardianCheck.denied) {
@@ -1,164 +0,0 @@
1
- import * as net from 'node:net';
2
-
3
- import {
4
- clearPIN,
5
- getParentalControlSettings,
6
- hasPIN,
7
- setPIN,
8
- updateParentalControlSettings,
9
- verifyPIN,
10
- } from '../../security/parental-control-store.js';
11
- import { getLogger } from '../../util/logger.js';
12
- import type {
13
- ParentalControlGetRequest,
14
- ParentalControlSetPinRequest,
15
- ParentalControlUpdateRequest,
16
- ParentalControlVerifyPinRequest,
17
- } from '../ipc-protocol.js';
18
- import { defineHandlers, type HandlerContext } from './shared.js';
19
-
20
- const log = getLogger('parental-control');
21
-
22
- function sendGetResponse(socket: net.Socket, ctx: HandlerContext): void {
23
- const settings = getParentalControlSettings();
24
- ctx.send(socket, {
25
- type: 'parental_control_get_response',
26
- enabled: settings.enabled,
27
- has_pin: hasPIN(),
28
- content_restrictions: settings.contentRestrictions,
29
- blocked_tool_categories: settings.blockedToolCategories,
30
- });
31
- }
32
-
33
- export function handleParentalControlGet(
34
- _msg: ParentalControlGetRequest,
35
- socket: net.Socket,
36
- ctx: HandlerContext,
37
- ): void {
38
- sendGetResponse(socket, ctx);
39
- }
40
-
41
- export function handleParentalControlVerifyPin(
42
- msg: ParentalControlVerifyPinRequest,
43
- socket: net.Socket,
44
- ctx: HandlerContext,
45
- ): void {
46
- const verified = verifyPIN(msg.pin);
47
- ctx.send(socket, {
48
- type: 'parental_control_verify_pin_response',
49
- verified,
50
- });
51
- }
52
-
53
- export function handleParentalControlSetPin(
54
- msg: ParentalControlSetPinRequest,
55
- socket: net.Socket,
56
- ctx: HandlerContext,
57
- ): void {
58
- try {
59
- const pinExists = hasPIN();
60
-
61
- if (msg.clear) {
62
- // Clearing the PIN — must verify current PIN first
63
- if (pinExists) {
64
- if (!msg.current_pin || !verifyPIN(msg.current_pin)) {
65
- ctx.send(socket, {
66
- type: 'parental_control_set_pin_response',
67
- success: false,
68
- error: 'Current PIN is incorrect',
69
- });
70
- return;
71
- }
72
- }
73
- clearPIN();
74
- ctx.send(socket, {
75
- type: 'parental_control_set_pin_response',
76
- success: true,
77
- });
78
- return;
79
- }
80
-
81
- if (!msg.new_pin) {
82
- ctx.send(socket, {
83
- type: 'parental_control_set_pin_response',
84
- success: false,
85
- error: 'new_pin is required',
86
- });
87
- return;
88
- }
89
-
90
- if (pinExists) {
91
- // Changing existing PIN — must verify current PIN first
92
- if (!msg.current_pin || !verifyPIN(msg.current_pin)) {
93
- ctx.send(socket, {
94
- type: 'parental_control_set_pin_response',
95
- success: false,
96
- error: 'Current PIN is incorrect',
97
- });
98
- return;
99
- }
100
- }
101
-
102
- setPIN(msg.new_pin);
103
- ctx.send(socket, {
104
- type: 'parental_control_set_pin_response',
105
- success: true,
106
- });
107
- } catch (err) {
108
- log.error({ err }, 'Failed to set parental control PIN');
109
- ctx.send(socket, {
110
- type: 'parental_control_set_pin_response',
111
- success: false,
112
- error: err instanceof Error ? err.message : 'Internal error',
113
- });
114
- }
115
- }
116
-
117
- export function handleParentalControlUpdate(
118
- msg: ParentalControlUpdateRequest,
119
- socket: net.Socket,
120
- ctx: HandlerContext,
121
- ): void {
122
- const settings = getParentalControlSettings();
123
- const pinExists = hasPIN();
124
-
125
- // Require PIN verification when parental mode is already enabled
126
- if (settings.enabled && pinExists) {
127
- if (!msg.pin || !verifyPIN(msg.pin)) {
128
- ctx.send(socket, {
129
- type: 'parental_control_update_response',
130
- success: false,
131
- error: 'PIN required to change parental control settings',
132
- enabled: settings.enabled,
133
- has_pin: pinExists,
134
- content_restrictions: settings.contentRestrictions,
135
- blocked_tool_categories: settings.blockedToolCategories,
136
- });
137
- return;
138
- }
139
- }
140
-
141
- const updated = updateParentalControlSettings({
142
- enabled: msg.enabled,
143
- contentRestrictions: msg.content_restrictions,
144
- blockedToolCategories: msg.blocked_tool_categories,
145
- });
146
-
147
- log.info({ enabled: updated.enabled }, 'Parental control settings updated');
148
-
149
- ctx.send(socket, {
150
- type: 'parental_control_update_response',
151
- success: true,
152
- enabled: updated.enabled,
153
- has_pin: hasPIN(),
154
- content_restrictions: updated.contentRestrictions,
155
- blocked_tool_categories: updated.blockedToolCategories,
156
- });
157
- }
158
-
159
- export const parentalControlHandlers = defineHandlers({
160
- parental_control_get: handleParentalControlGet,
161
- parental_control_verify_pin: handleParentalControlVerifyPin,
162
- parental_control_set_pin: handleParentalControlSetPin,
163
- parental_control_update: handleParentalControlUpdate,
164
- });
@@ -1,109 +0,0 @@
1
- // Parental control IPC types.
2
- //
3
- // The parental control system lets a parent or guardian lock the assistant
4
- // behind a 6-digit PIN and configure per-topic content restrictions and
5
- // per-category tool blocks. All mutating operations require the PIN when
6
- // one has been set.
7
-
8
- // === Shared data types ===
9
-
10
- /**
11
- * Topics that can be individually blocked.
12
- * All unlisted topics are allowed.
13
- */
14
- export type ParentalContentTopic =
15
- | 'violence'
16
- | 'adult_content'
17
- | 'political'
18
- | 'gambling'
19
- | 'drugs';
20
-
21
- /**
22
- * Broad tool categories that can be disabled for age-appropriate use.
23
- * When a category is blocked, individual tool invocations within that
24
- * category are rejected before the permission pipeline runs.
25
- */
26
- export type ParentalToolCategory =
27
- | 'computer_use'
28
- | 'network'
29
- | 'shell'
30
- | 'file_write';
31
-
32
- // === Client → Server ===
33
-
34
- /** Retrieve the current parental control settings and PIN status. */
35
- export interface ParentalControlGetRequest {
36
- type: 'parental_control_get';
37
- }
38
-
39
- /** Verify a PIN attempt without changing any state. Useful to gate an unlock-settings flow before showing the full panel. */
40
- export interface ParentalControlVerifyPinRequest {
41
- type: 'parental_control_verify_pin';
42
- pin: string;
43
- }
44
-
45
- /** Set, change, or clear the parental control PIN. To set for the first time provide only new_pin. To change provide current_pin and new_pin. To clear provide current_pin and set clear:true. */
46
- export interface ParentalControlSetPinRequest {
47
- type: 'parental_control_set_pin';
48
- current_pin?: string;
49
- new_pin?: string;
50
- clear?: boolean;
51
- }
52
-
53
- /** Update parental control settings. Requires the PIN when parental mode is already enabled. */
54
- export interface ParentalControlUpdateRequest {
55
- type: 'parental_control_update';
56
- /** Current PIN — required when parental mode is already enabled. */
57
- pin?: string;
58
- /** Enable or disable parental control mode. */
59
- enabled?: boolean;
60
- /** Full replacement list of blocked content topics. */
61
- content_restrictions?: ParentalContentTopic[];
62
- /** Full replacement list of blocked tool categories. */
63
- blocked_tool_categories?: ParentalToolCategory[];
64
- }
65
-
66
- // === Server → Client ===
67
-
68
- export interface ParentalControlGetResponse {
69
- type: 'parental_control_get_response';
70
- enabled: boolean;
71
- has_pin: boolean;
72
- content_restrictions: ParentalContentTopic[];
73
- blocked_tool_categories: ParentalToolCategory[];
74
- }
75
-
76
- export interface ParentalControlVerifyPinResponse {
77
- type: 'parental_control_verify_pin_response';
78
- verified: boolean;
79
- }
80
-
81
- export interface ParentalControlSetPinResponse {
82
- type: 'parental_control_set_pin_response';
83
- success: boolean;
84
- error?: string;
85
- }
86
-
87
- export interface ParentalControlUpdateResponse {
88
- type: 'parental_control_update_response';
89
- success: boolean;
90
- error?: string;
91
- enabled: boolean;
92
- has_pin: boolean;
93
- content_restrictions: ParentalContentTopic[];
94
- blocked_tool_categories: ParentalToolCategory[];
95
- }
96
-
97
- // --- Domain-level union aliases (consumed by the barrel file) ---
98
-
99
- export type _ParentalControlClientMessages =
100
- | ParentalControlGetRequest
101
- | ParentalControlVerifyPinRequest
102
- | ParentalControlSetPinRequest
103
- | ParentalControlUpdateRequest;
104
-
105
- export type _ParentalControlServerMessages =
106
- | ParentalControlGetResponse
107
- | ParentalControlVerifyPinResponse
108
- | ParentalControlSetPinResponse
109
- | ParentalControlUpdateResponse;