GRC SCRIPING

 GRC/IRM use cases for every Business Rule type.


1. After Business Rule – (Most used in GRC – 45%)

Runs after record is saved.
Use Cases:

  • Auto-create Issue when Control Test fails

  • Auto-calculate Inherent and Residual Risk

  • Update Risk Score when likelihood/impact changes

  • Cascade status to parent Risk/Control

  • Auto-close tasks when evidence submitted

  • Create Remediation Task when Issue is “High”

  • Sync fields between Control and Entity Scope


2. Before Business Rule – (25%)

Modifies data before insert/update.
Use Cases:

  • Set default Owner, Category, Domain

  • Auto-populate Control Type or Risk Class based on mapping

  • Prevent update if record is in finalized/approved state

  • Correct wrong data before save (e.g., normalize scores)

  • Make certain fields mandatory depending on state


3. Async Business Rule – (20%)

Runs in background.
Use Cases:

  • Create dependent tasks without delaying form submit

  • Send notifications (assessment due, evidence overdue)

  • Recalculate scores for all children after update

  • Log audit records for compliance activity

  • Update related GRC table counts (KRIs, Controls, Risks)


4. Display Business Rule – (10%)

Runs on form load.
Use Cases:

  • Show user-specific data: “Your pending assessments count”

  • Calculate UI-only values (not stored in DB)

  • Pre-fill related info without saving (e.g., Control Maturity trend)

  • Make server values available for client scripts

  • Display warning messages on form open


==================================================

 GlideRecord – Use Cases

  • Fetch all controls mapped to a Risk

  • Get all open Issues for a Control

  • Create Issues/Tasks programmatically

  • Update child tasks when parent Risk changes

  • Retrieve all Entity Scopes for a Control Test

  • Bulk update assessment results

  • Validate uniqueness (e.g., duplicate risk names)


20 GlideRecord Tasks (GRC/IRM)

1. Fetch all open Issues

var r = new GlideRecord('sn_grc_issue'); r.addQuery('state','open'); r.query();

2. Update all failed Controls to “Review”

var c = new GlideRecord('sn_grc_control_test'); c.addQuery('result','fail'); c.query(); while(c.next()){c.state='review'; c.update();}

3. Get all Controls for a specific Risk

var c = new GlideRecord('sn_grc_control'); c.addQuery('risk', current.sys_id); c.query();

4. Create Issue when control fails

var i = new GlideRecord('sn_grc_issue'); i.newRecord(); i.control=current.sys_id; i.insert();

5. Update Residual Score for all Risks

var r = new GlideRecord('sn_grc_risk'); r.query(); while(r.next()){ r.residual_score=r.impact*r.likelihood; r.update(); }

6. Delete old remediation tasks

var t = new GlideRecord('sn_grc_task'); t.addQuery('sys_created_on','<',gs.daysAgo(365)); t.deleteMultiple();

7. Find all Risks without Controls

var r = new GlideRecord('sn_grc_risk'); r.addNullQuery('control'); r.query();

8. Get all Evidence records for a test

var e = new GlideRecord('sn_grc_evidence'); e.addQuery('parent', current.sys_id); e.query();

9. Count open Issues

var r=new GlideAggregate('sn_grc_issue'); r.addAggregate('COUNT'); r.query(); r.getAggregate('COUNT');

10. Check if duplicate Risk name exists

var r=new GlideRecord('sn_grc_risk'); r.addQuery('name',current.name); r.query();

11. Auto-assign owner from related Entity

var e = new GlideRecord('sn_grc_entity'); e.get(current.entity); current.owner=e.owner;

12. Get last control test for same Control

var c=new GlideRecord('sn_grc_control_test'); c.addQuery('control',current.control); c.orderByDesc('sys_created_on'); c.query(); c.next();

13. Bulk close completed assessments

var a=new GlideRecord('sn_grc_assessment'); a.addQuery('status','complete'); a.query(); while(a.next()) a.state='closed', a.update();

14. Create Control Test tasks

var t=new GlideRecord('sn_grc_control_test'); t.newRecord(); t.control=current.sys_id; t.insert();

15. Move all related Issues to “In Review”

var i=new GlideRecord('sn_grc_issue'); i.addQuery('control',current.sys_id); i.query(); while(i.next()){i.state='review'; i.update();}

16. Get KRIs for a Risk

var k=new GlideRecord('sn_grc_kri'); k.addQuery('risk', current.sys_id); k.query();

17. Disable inactive controls

var c=new GlideRecord('sn_grc_control'); c.addQuery('active',true); c.query(); while(c.next()){ if(c.status=='retired'){c.active=false; c.update();}}

18. Find overdue GRC tasks

var t=new GlideRecord('sn_grc_task'); t.addQuery('due_date','<',gs.now()); t.addQuery('state','!=','closed'); t.query();

19. Backfill Domain on Risks

var r=new GlideRecord('sn_grc_risk'); r.query(); while(r.next()){r.domain='global'; r.update();}

20. Fetch all Controls with failed last test

var c=new GlideRecord('sn_grc_control'); c.addQuery('last_test_result','fail'); c.q



=========================================================


 Script Include – Use Cases

  • Centralized Risk Score calculation

  • Standard function to create Issues

  • Fetch all residual scores for dashboard widgets

  • Common utility: getAllControls(), getAllTasks()

  • Reusable Evidence Validation logic

  • Impact & Likelihood matrix stored in one place

  • Data sync between Risk, Control, Issue modules




20 SCRIPT INCLUDE TASKS (GRC/IRM)

1. Calculate Risk Score

calc:function(c){return c.impact*c.likelihood;}


2. Create Issue from any module

createIssue:function(r){var i=new GlideRecord('sn_grc_issue');i.newRecord();i.risk=r;return i.insert();}


3. Get all controls for a Risk

getControls:function(r){var c=new GlideRecord('sn_grc_control');c.addQuery('risk',r);c.query();return c;}


4. Validate Evidence (size/type)

validate:function(e){return e.type=='pdf';}


5. Get residual score trend (last 6 months)

trend:function(r){/*query history table*/ }


6. Reusable function to update child tasks

updateChild:function(p){/*loop child tasks*/ }


7. Auto-assign Owner based on Entity

owner:function(ent){var e=new GlideRecord('sn_grc_entity');e.get(ent);return e.owner;}


8. Common utility for date comparison

isOverdue:function(d){return d<gs.now();}


9. Create Control Test programmatically

createTest:function(c){var t=new GlideRecord('sn_grc_control_test');t.newRecord();t.control=c;return t.insert();}


10. Fetch all Issues for a Control

issues:function(c){var i=new GlideRecord('sn_grc_issue');i.addQuery('control',c);i.query();return i;}


11. Cascade score to parent Risk

cascade:function(r){/*get children, recalc*/ }


12. Utility to send reminder email

remind:function(u){gs.eventQueue('grc.reminder',null,u);}


13. Fetch open assessments for a user

assess:function(u){var a=new GlideRecord('sn_grc_assessment');a.addQuery('assigned_to',u);a.query();return a;}


14. Normalize scoring fields

normalize:function(v){return Math.min(v,5);}


15. Check if Risk already exists

exists:function(n){var r=new GlideRecord('sn_grc_risk');r.addQuery('name',n);r.query();return r.hasNext();}


16. Fetch entity-scoped controls

entityControls:function(e){var c=new GlideRecord('sn_grc_control');c.addQuery('entity',e);c.query();return c;}


17. Reusable GlideRecord wrapper

get:function(t,q){var g=new GlideRecord(t);g.addQuery(q.f,q.v);g.query();return g;}


18. Validate Risk Category logic

validCat:function(c){return ['Tech','Ops'].indexOf(c)>-1;}


19. Sync data between Risk → Issue

sync:function(r,i){i.category=r.category; i.owner=r.owner;}


20. Generic insert utility

insertRec:function(t,o){var g=new GlideRecord(t);g.newRecord();for(var k in o)g[k]=o[k];return g.insert();}

Comments