The Veil2 scopes table is an
    important link between Veil2 and the database
    that it is protecting.  It provides the semantic link between
    scopes as understood by the security
    model, and the security
    contexts provided or implied by the data model: it maps
    logical scopes in the protected database, to
    Veil2's physical scopes, keyed by
    scope_type_id and scope_id.
  
    Look for STEP 5 in the file
    veil2_demo--<version>.sql.
  
      You will start by creating a table that inherits from
      veil2.scopes.  To this
      you will add columns that reference your tables.
    
      For instance if you have a project context based on a user's
      membership of projects, and your project
      table has an integer project_id field as its
      primary key, you would do the following:
      
create table veil2.scope_links (
  party_id 	integer,
  project_id	integer
) inherits (veil2.scopes);
-- Set PK and FKs to match those in the parent scopes table
alter table veil2.scope_links add constraint scope_link__pk
  primary key(scope_type_id, scope_id);
alter table veil2.scope_links add constraint scope_link__type_fk
  foreign key(scope_type_id)
  references veil2.scope_types;
alter table veil2.scope_links
  add constraint scope_link__party_fk
  foreign key (party_id)
  references demo.parties_tbl(party_id)
  on delete cascade;
alter table veil2.scope_links
  add constraint scope_link__project_fk
  foreign key (project_id)
  references demo.projects(project_id)
  on on delete cascade;
      
      Using the cascade options ensures that deletions of record in
      the projects table are propagated to
      scopes.  This saves us from having to
      implement our own triggers for deletions.
    
It is wise to also ensure that project_id fields are only used with the appropriate scope type. A check constraint like the following should be used:
alter table veil2.scope_links
  add constraint scope_link__check_fk_type
  check (case
         when scope_type_id in (3, 4) then
              party_id is not null
	 when scope_type_id = 5 then
	      project_id is not null
	 else true end);
      
      Where, we assume, a scope_type_id of
      5 means project scope, 4
      means org scope and 3 means corp scope.
    
	If the linked scope in your protected database uses a simple
	integer primary key, this can safely be used as the
	scope_id in the links table as the primary
	key of a scope is the combination of
	scope_type_id and
	scope_id.
      
	If your source table's primary key is of some other form you
	could simply allocate a scope_id for the
	link table from a sequence, however each call to i_have_priv_in_scope()
	will now need to map to the Veil2 scope key
	through our links table.  This is likely to badly affect
	performance.
      
	In such a case, we recommend refactoring your source table to
	include a new unique integer key which can be used in the link
	table as both the foreign key to the source scope, and as part
	of the primary key to Veil2's scope.
      
We need to ensure that new scopes (in the demo these are projects, orgs and corps) created in the underlying tables are automatically propagated to the scopes tables. Triggers on insert to those tables should be created do do this.
There should be no need for update or delete triggers as we have defined our foreign key constraint to cascade updates and deletes.
Next, we want to ensure that the keys used by scopes do not change, or that if they do, we handle it.
Ideally our on-update trigger function will ensure that the scope's key fields do not change and cause an error if an attempt is made to do so.
If, for some reason, key changes must be allowed, then we must propagate such changes into our scope_links table, and we must clear all caches and refresh all materialized views that may be affected.
      Now we need to copy our existing scope records into our new
      scope_links table.
      projects.  Something like this (for projects):
      
insert
  into veil2.scope_links
      (scope_type_id, scope_id, project_id)
select 5, project_id, project_id
  from demo.projects;
      
      If you have role assignments that are not managed solely through
      the veil2.accessor_roles table, you will need
      to modify the all_accessor_roles
      view.  For example, in the demo, roles are assigned in project
      context using the demo.project_assignments
      table.
    
      To enable the creation of custom security contexts,
      Veil2 determines an accessor's roles and the
      contexts in which they apply from the
      veil2.all_accessor_roles view, which you can
      modify by providing your own
      veil2.my_all_accessor_roles.
    
      In the demo we make this view return results from both the
      veil2.accessor_roles and the
      demo.project_assignments tables.
    
      For performance reasons Veil2 caches a lot of scope-related privilege
      data.  Some steps in your Veil2 VPD
      implementation will require the explicit clearing or refreshing
      of some or all of those caches.
    
Changes to scopes do not require the refresh of materialized views or the clearing of caches. The rationale for this is as follows:
In the event of a new scope being created, there can exist no records relating to that scope (assuming that you cannot create descendent records of your scopes before creating the scope itself - ie we assume proper referential integrity is being maintained in the source database), particularly records relating to role assignments, so there can be no new privileges or roles assigned to any users and therefore no need to update the caches.
In the event of scope deletion, there will be no records remaining in that scope to which access must be controlled, so temporarily retaining redundant privileges for dead scopes can have no security implications.
Updates to the scope keys are the only situation where we may need to clear caches and refresh materialized views, and we strongly recommend that triggers are put in place to prevent such updates.
	All changes to role assignments must result in accessor_privileges_cache
	entries being cleared for the accessor in question.
      
	This should be done by adding triggers to the tables
	underlying your version of the
	all_accessor_roles view.  These triggers
	should call veil2.clear_accessor_privs_cache_entry()
	or veil2.clear_accessor_privs_cache().