Skip to content

Getting Started

This guide uses Snowflake as the example platform. The workflow is similar across platforms.

  • Snowflake Enterprise Edition (required for masking policies)
  • VEIL installed and services running
  • A table with numeric feature columns

These procedures require the app_admin role.

Check that services are running:

CALL veil.core.service_status();

Wait for both services to reach ready (blocks up to 10 minutes):

CALL veil.core.wait_for_services();

Test that encoding works (app_user or app_admin):

SELECT veil.core.encode('sample', ARRAY_CONSTRUCT(1.0, 2.0, 3.0, 4.0));

Returns an encoded vector like [0.23, -0.41, 0.87, 0.12].

Create a feature view that bundles columns into an array, then protect it.

Create a feature view (hides column names from queries):

CALL veil.create_feature_view(
'my_db.my_schema.sales',
'sales',
ARRAY_CONSTRUCT('price', 'sqft', 'bedrooms', 'bathrooms'),
ARRAY_CONSTRUCT('year_built')
);

Protect the features column:

CALL veil.protect_column(
'my_db.my_schema.sales_v',
'features'
);

Now query the view:

SELECT year_built, features FROM my_db.my_schema.sales_v LIMIT 3;

As an admin, you see raw feature arrays. As an analyst, you see encoded vectors. The analyst can group by year_built and use features for ML, but cannot see raw values or join to external records.

Passthrough columns are validated against an identifier denylist. Common identifier names (id, *_id, email, ssn, phone, name, address, account, customer, user) are rejected by default.

To allow identifier columns explicitly:

CALL veil.create_feature_view(
'my_db.my_schema.sales', 'sales',
ARRAY_CONSTRUCT('price', 'sqft', 'bedrooms', 'bathrooms'),
ARRAY_CONSTRUCT('parcel'),
TRUE
);

The bundled sample encoder is generic. For production, train on your data.

Start training (runs on CPU by default, GPU optional):

CALL veil.train_encoder(
'sales',
'my_db.my_schema.sales',
ARRAY_CONSTRUCT('price', 'sqft', 'bedrooms', 'bathrooms'),
16,
100,
256,
ARRAY_CONSTRUCT('year_built')
);

Monitor progress:

SELECT encoder_name, status, progress
FROM veil.training_jobs_v
WHERE encoder_name = 'sales';

Once complete, generate the view from encoder metadata:

CALL veil.create_view_from_encoder('sales');

Protect the features column:

CALL veil.protect_column('my_db.my_schema.sales_v', 'features');

Retraining an existing encoder is allowed. The previous version is archived automatically.

CALL veil.unprotect_column('my_db.my_schema.sales_v', 'features');

For simple cases (one sensitive value like salary), you can protect a column directly without a feature view:

CALL veil.protect_column('my_db.my_schema.employees', 'salary', 'sample');

View archived encoder versions:

SELECT * FROM veil.encoder_versions_v WHERE encoder_name = 'sales';

Training runs on CPU by default. To switch to GPU (requires app_admin):

CALL veil.core.set_training_compute('gpu');
CALL veil.core.start_services();

To switch back to CPU:

CALL veil.core.set_training_compute('cpu');
CALL veil.core.start_services();