mcpField
D
data-policies

data-policies

github.com/serac-labsデータ・データベース7759 回インストール9 週間前に更新
リポジトリ

data-policies について

ServiceNow 開発者向けに、テーブルやフィールドの定義とデータ整合性を保つポリシー規則を解説するガイドです。ES5 の例、スキーマ検索方法、関連する MCP ツールを紹介します。

主な機能

  1. 01テーブルとフィールド定義の管理
  2. 02辞書オーバーライドと選択肢の設定
  3. 03データポリシーとルールの作成
  4. 04フィールド検証とスキーマ検索
  5. 05関連する MCP ツールの紹介

活用シーン

  1. 01カスタムテーブルのフィールド設計
  2. 02レコードへの業務データ要件の適用
  3. 03テーブル項目やポリシー設定の確認

MCP 対応

辞書とデータポリシーの操作に使う ServiceNow MCP ツールとして、snow_query_table、snow_discover_table_fields、snow_execute_script を挙げています。フィールド定義の確認やデータポリシー検索の例もあります。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/serac-labs/serac --skill data-policies

インストール後、Claude Code で/data-policiesを入力して読み込まれたか確認します。

詳細

ServiceNow のデータポリシーとディクショナリ

データポリシーはデータ整合性ルールを適用します。ディクショナリはスキーマとフィールドの動作を制御します。

アーキテクチャ

Dictionary (sys_dictionary)
    ├── Field Definition
    │   ├── Type, Length, Default
    │   └── Dependent Field
    └── Dictionary Overrides (sys_dictionary_override)

Data Policy (sys_data_policy2)
    └── Data Policy Rules (sys_data_policy_rule)
        └── Condition-based field behaviors

主なテーブル

テーブル用途
sys_dictionaryフィールド定義
sys_dictionary_overrideスコープ付きの上書き
sys_data_policy2データポリシー
sys_data_policy_ruleポリシールール
sys_db_objectテーブル定義

ディクショナリの管理(ES5)

テーブルの作成
// Create custom table (ES5 ONLY!)
var table = new GlideRecord("sys_db_object")
table.initialize()

table.setValue("name", "u_custom_table")
table.setValue("label", "Custom Table")
table.setValue("super_class", "task") // Extends task
table.setValue("is_extendable", true)
table.setValue("create_access_controls", true)
table.setValue("live_feed_enabled", false)

table.insert()
フィールドの作成
// Create field on table (ES5 ONLY!)
var field = new GlideRecord("sys_dictionary")
field.initialize()

// Table and element
field.setValue("name", "u_custom_table")
field.setValue("element", "u_customer_name")

// Field properties
field.setValue("column_label", "Customer Name")
field.setValue("internal_type", "string")
field.setValue("max_length", 100)
field.setValue("mandatory", false)
field.setValue("read_only", false)
field.setValue("display", false)
field.setValue("active", true)

// Default value
field.setValue("default_value", "")

// Reference field specific
// field.setValue('reference', 'customer_account');
// field.setValue('reference_qual', 'active=true');

field.insert()
フィールドの種類
// Common field types
var FIELD_TYPES = {
  STRING: "string",
  INTEGER: "integer",
  DECIMAL: "decimal",
  BOOLEAN: "boolean",
  GLIDE_DATE: "glide_date",
  GLIDE_DATE_TIME: "glide_date_time",
  REFERENCE: "reference",
  CHOICE: "choice",
  JOURNAL: "journal",
  JOURNAL_INPUT: "journal_input",
  HTML: "html",
  URL: "url",
  EMAIL: "email",
  SCRIPT: "script",
  CONDITIONS: "conditions",
}

// Create different field types (ES5 ONLY!)
function createField(tableName, fieldDef) {
  var field = new GlideRecord("sys_dictionary")
  field.initialize()
  field.setValue("name", tableName)
  field.setValue("element", fieldDef.name)
  field.setValue("column_label", fieldDef.label)
  field.setValue("internal_type", fieldDef.type)

  if (fieldDef.maxLength) {
    field.setValue("max_length", fieldDef.maxLength)
  }

  if (fieldDef.reference) {
    field.setValue("reference", fieldDef.reference)
  }

  if (fieldDef.choices) {
    field.setValue("choice", 1) // Has choices
  }

  return field.insert()
}
選択肢の作成
// Create choice list values (ES5 ONLY!)
function createChoices(tableName, fieldName, choices) {
  for (var i = 0; i < choices.length; i++) {
    var choice = new GlideRecord("sys_choice")
    choice.initialize()
    choice.setValue("name", tableName)
    choice.setValue("element", fieldName)
    choice.setValue("value", choices[i].value)
    choice.setValue("label", choices[i].label)
    choice.setValue("sequence", (i + 1) * 10)
    choice.setValue("inactive", false)
    choice.insert()
  }
}

// Usage
createChoices("incident", "u_custom_status", [
  { value: "pending", label: "Pending Review" },
  { value: "approved", label: "Approved" },
  { value: "rejected", label: "Rejected" },
])

ディクショナリの上書き(ES5)

上書きの作成
// Create dictionary override for scoped app (ES5 ONLY!)
var override = new GlideRecord("sys_dictionary_override")
override.initialize()

// Reference the base field
override.setValue("base_table", "task")
override.setValue("base_element", "short_description")

// Target table
override.setValue("name", "u_custom_table")

// Override properties
override.setValue("column_label", "Request Summary")
override.setValue("mandatory", true)
override.setValue("read_only", false)
override.setValue("max_length", 200)

// Default value override
override.setValue("default_value", "")

override.insert()

データポリシー(ES5)

データポリシーの作成
// Create data policy (ES5 ONLY!)
var policy = new GlideRecord("sys_data_policy2")
policy.initialize()

policy.setValue("model_table", "incident")
policy.setValue("short_description", "Resolution Fields Required on Resolve")
policy.setValue("active", true)

// Conditions - when policy applies
policy.setValue("conditions", "state=6") // Resolved state

// Apply to forms
policy.setValue("apply_to_client", true)
policy.setValue("apply_to_import_sets", true)
policy.setValue("apply_to_soap", true)

// Reverse
policy.setValue("reverse_if_false", true)

var policySysId = policy.insert()

// Add policy rules
addDataPolicyRule(policySysId, "resolution_code", true, false, false)
addDataPolicyRule(policySysId, "close_notes", true, false, false)
ポリシールールの追加
// Add data policy rule (ES5 ONLY!)
function addDataPolicyRule(policySysId, fieldName, mandatory, readOnly, hidden) {
  var rule = new GlideRecord("sys_data_policy_rule")
  rule.initialize()
  rule.setValue("sys_data_policy", policySysId)
  rule.setValue("field", fieldName)
  rule.setValue("mandatory", mandatory)
  rule.setValue("read_only", readOnly)
  rule.setValue("visible", !hidden)
  return rule.insert()
}
複雑なデータポリシー
// Data policy with scripted condition (ES5 ONLY!)
var policy = new GlideRecord("sys_data_policy2")
policy.initialize()

policy.setValue("model_table", "change_request")
policy.setValue("short_description", "High Risk Change Requirements")
policy.setValue("active", true)

// Use scripted condition for complex logic
policy.setValue("use_as_condition", true)
policy.setValue(
  "script",
  "(function checkCondition(current) {\n" +
    "    // High risk changes require additional fields\n" +
    '    if (current.risk == "high") {\n' +
    "        return true;\n" +
    "    }\n" +
    "    \n" +
    "    // Also apply to changes affecting critical CIs\n" +
    "    if (current.cmdb_ci) {\n" +
    "        var ci = current.cmdb_ci.getRefRecord();\n" +
    '        if (ci.business_criticality == "1 - most critical") {\n' +
    "            return true;\n" +
    "        }\n" +
    "    }\n" +
    "    \n" +
    "    return false;\n" +
    "})(current);",
)

var policySysId = policy.insert()

// Require additional documentation for high risk
addDataPolicyRule(policySysId, "implementation_plan", true, false, false)
addDataPolicyRule(policySysId, "backout_plan", true, false, false)
addDataPolicyRule(policySysId, "test_plan", true, false, false)
addDataPolicyRule(policySysId, "justification", true, false, false)

フィールドの検証(ES5)

ディクショナリ属性の検証
// Add validation to dictionary field (ES5 ONLY!)
var field = new GlideRecord("sys_dictionary")
if (field.get("name", "incident").get("element", "u_email")) {
  // Add regex validation
  field.setValue("attributes", "validate=email")
  field.update()
}

// Common validation attributes
var VALIDATION_ATTRIBUTES = {
  EMAIL: "validate=email",
  PHONE: "validate=phone_number",
  URL: "validate=url",
  CUSTOM: "validate=script", // Uses script in Calculated Value
}
スクリプトによる検証
// Calculated field with validation (ES5 ONLY!)
// Set in Dictionary > Calculated Value

// Check phone format
;(function calculate() {
  var phone = current.getValue("u_phone")
  if (!phone) return ""

  // Format validation
  var phonePattern = /^\+?[1-9]\d{1,14}$/
  if (!phonePattern.test(phone.replace(/[\s\-\(\)]/g, ""))) {
    gs.addErrorMessage("Invalid phone number format")
    return ""
  }

  return phone
})()

スキーマのクエリ(ES5)

テーブルのフィールドを取得
// Get all fields for a table (ES5 ONLY!)
function getTableFields(tableName) {
  var fields = []

  var dict = new GlideRecord("sys_dictionary")
  dict.addQuery("name", tableName)
  dict.addQuery("internal_type", "!=", "collection")
  dict.addQuery("active", true)
  dict.orderBy("element")
  dict.query()

  while (dict.next()) {
    fields.push({
      name: dict.getValue("element"),
      label: dict.getValue("column_label"),
      type: dict.getValue("internal_type"),
      mandatory: dict.getValue("mandatory") === "true",
      reference: dict.getValue("reference"),
      maxLength: dict.getValue("max_length"),
    })
  }

  return fields
}
フィールドの存在を確認
// Check if field exists on table (ES5 ONLY!)
function fieldExists(tableName, fieldName) {
  var dict = new GlideRecord("sys_dictionary")
  dict.addQuery("name", tableName)
  dict.addQuery("element", fieldName)
  dict.query()
  return dict.hasNext()
}

MCP ツールの統合

利用可能なツール
ツール用途
snow_query_tableディクショナリとデータポリシーをクエリ
snow_discover_table_fieldsフィールド定義を取得
snow_execute_scriptディクショナリスクリプトをテスト
ワークフローの例
// 1. Get table fields
await snow_discover_table_fields({
  table_name: "incident",
})

// 2. Query data policies
await snow_query_table({
  table: "sys_data_policy2",
  query: "model_table=incident^active=true",
  fields: "short_description,conditions,apply_to_client",
})

// 3. Check dictionary overrides
await snow_query_table({
  table: "sys_dictionary_override",
  query: "name=u_custom_table",
  fields: "base_element,column_label,mandatory,read_only",
})

ベストプラクティス

  1. スキーマの計画 - 実装前に設計します
  2. フィールドの命名 - カスタムフィールドには u_ プレフィックスを使用します
  3. データ型 - 適切な型を使用します
  4. 必須フィールド - 本当に必要な場合にのみ設定します
  5. データポリシー - ビジネスルールを適用します
  6. パフォーマンス - 複雑な計算フィールドは避けます
  7. ドキュメント - カスタムスキーマを文書化します
  8. ES5 のみ - モダンな JavaScript 構文は使用しません

コメント